Toarnbeike.Results
1.0.0
dotnet add package Toarnbeike.Results --version 1.0.0
NuGet\Install-Package Toarnbeike.Results -Version 1.0.0
<PackageReference Include="Toarnbeike.Results" Version="1.0.0" />
<PackageVersion Include="Toarnbeike.Results" Version="1.0.0" />
<PackageReference Include="Toarnbeike.Results" />
paket add Toarnbeike.Results --version 1.0.0
#r "nuget: Toarnbeike.Results, 1.0.0"
#:package Toarnbeike.Results@1.0.0
#addin nuget:?package=Toarnbeike.Results&version=1.0.0
#tool nuget:?package=Toarnbeike.Results&version=1.0.0
Toarnbeike.Results
Toarnbeike.Results is a lightweight, expressive C# implementation of the Result monad. It enhances code clarity and reliability by enabling clear, exception-free handling of success, failure, and validation outcomes.
Features
- Explicit error handling: Avoid exceptions for control flow; return meaningful failures instead.
- Fluent extension methods: Compose operations with
Bind
,Map
,Match
,Tap
, and more. - Strongly typed generic results: Preserve either a success value or failure details in one type-safe container.
- Rich validation support: Aggregate validation failures with rich property-level details.
- Seamless integration: All methods support asynchronous pipelines.
- Functional programming inspired: Inspired by FP principles for predictable, readable, and maintainable error handling.
Core concepts
Result
: Represents a successful or failed operation.Result<TValue>
: A Result carrying a value on success.Failure
: Encapsulates error details, including validation failures.ValidationFailure
: Describes a property-level validation issue.AggregateFailure
: Represents grouped validation failures.
Packages
Inspiration
This project draws inspiration from:
Getting Started
dotnet add package Toarnbeike.Results
Then import on or more of the following namespaces:
using Toarnbeike.Results; // Base namespace for Result, Result<TValue> and Failure
using Toarnbeike.Results.Collections; // For extensions on IEnumerable<Result<T>>
using Toarnbeike.Results.Extensions; // For functional extensions on Result and Result<TValue>
using Toarnbeike.Results.Failure; // For additional failure types
using Toarnbeike.Results.Linq; // For LINQ query syntax support
using Toarnbeike.Results.TestHelpers; // For fluent assertions on results.
Basic Usage
A result can represent either success (with or without a value) or failure (with error details):
// Success Results
var result1 = Result.Success();
var result2 = Result<int>.Success(42);
var result3 = Result.Success(42); // Type inferred
Result<int> result4 = 42; // Implicit conversion
// Failure Results
var result4 = Result<int>.Failure(new Failure("Code", "Message"));
Result<int> result5 = new Failure("Code", "Message"); // implicit conversion
Extracting the value or the failure from the rsult:
if (result1.TryGetValue(out var value, out var failure))
{
Console.WriteLine(value); // 42
}
Extension Methods
The Toarnbeike.Results.Extensions
namespace includes rich extensions for Result
and Result<T>
:
Method | Result |
Result<T> |
Description |
---|---|---|---|
Bind(...) |
✅ | ✅ | Chains operations returning Result<TOut> |
Check(...) |
❌ | ✅ | Check a condition on the success value, or returns a failure |
Map(...) |
❌ | ✅ | Maps the success value to another type |
Match(...) |
✅ | ✅ | Converts to another type using success/failure lambdas |
Tap(...) |
✅ | ✅ | Executes side-effects on success |
TapAlways(...) |
✅ | ✅ | Executes side-effects on any result |
TapFailure(...) |
✅ | ✅ | Executes side-effects on failure |
Verify(...) |
✅ | ✅ | Verifies another result; propagates failure if needed |
VerifyWhen(...) |
✅ | ✅ | Conditionally verifies another result |
WithValue(...) |
✅ | ❌ | Adds a value to a non-generic result |
Zip(...) |
❌ | ✅ | Combines two results into a Result<(T1,T2)> |
All methods support async
variants and operate seamlessly with Task<Result<T>>
.
For information per method see the Extensions README.
Collections
The Toarnbeike.Results.Collections
namespace provides extension methods for working with collections of results:
Method | ReturnType | Description |
---|---|---|
AllSuccess() |
bool |
Returns true if all results in the collection are successful |
Sequence() |
Result<IEnumerable<T>> |
Returns all success values or the first encountered failure |
Aggregate() |
Result<IEnumerable<T>> |
Returns all success values or an AggregateFailure containing all failures |
SuccessValues() |
IEnumerable<T> |
Extracts all success values from a collection of results |
Failures() |
IEnumerable<Failure> |
Extracts all failures from a collection of results |
Split() |
(IEnumerable<T>, IEnumerable<Failure>) |
Splits the collection into success values and failures |
All methods support async
variants and operate seamlessly with IEnumerable<Task<Result<T>>>
.
Failures
The Toarnbeike.Results.Failures
namespace include a couple of default failures:
AggregateFailure
Represents a collection of multiple failures, typically used when working with collections of Result<T>
:
var results = new List<Result<int>>
{
Result<int>.Success(1),
Result<int>.Failure(new Failure("Code1", "Message1")),
Result<int>.Failure(new Failure("Code2", "Message2"))
};
var aggregateResult = results.Aggregate(); // Result<IEnumerable<int>>
var ggregateFailure = aggregateResult
.ShouldBeFailureOfType<AggregateFailure>();
ExceptionFailure
Used when converting exceptions to failures via the Try
factory:
var result1 = Result.Try(() => int.Parse("123")); // Success(123);
var result2 = Result.Try(() => int.Parse("abc")) // Failure(ExceptionFailure);
ValidationFailure
Represents a property-level validation issue:
new ValidationFailure("Email", "Email is required.");
ValidationFailures
Aggregates multiple ValidationFailure
instances. Typically produced using the FluentValidation
integration.
LINQ Query syntax support
Toarnbeike.Results supports optional integration with C# LINQ query syntax,
making it easier to compose multiple Result<T>
computations in a declarative style.
Why use LINQ Query Syntax?
While method chaining works well for most scenarios, C#�s LINQ query syntax can make some workflows more expressive and readable � especially when you want to:
- Name intermediate results using
let
- Compose complex Result pipelines in a declarative way
- Avoid deeply nested lambdas in
Bind
andMap
Example:
using Toarnbeike.Results.Linq;
var result =
from id in GetUserId()
from user in GetUserById(id)
let fullName = $"{user.FirstName} {user.LastName}"
select new UserDto(fullName, user.Email);
When comparing that with method chaining, the LINQ query syntax can be more readable, especially for complex workflows:
var result = GetUserId()
.Bind(GetUserById)
.Map(user =>
{
var name = $"{user.FirstName} {user.LastName}";
return new UserDto(name, user.Email);
});
Which also works, but makes name only available inside the Map
lambda.
TestHelpers
These are ideal for unit testing and compatible with any test framework. See the TestHelpers README for details.
Why Results?
Exceptions should be exceptional. Result<T> gives you clarity, safety, and composability � without relying on exceptions for control flow.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Toarnbeike.Results:
Package | Downloads |
---|---|
Toarnbeike.Results.FluentValidation
Integrating FluentValidation with Toarnbeike.Results |
|
Toarnbeike.Results.Optional
Convert between Toarnbeike.Results an Toarnbeike.Optional |
|
Toarnbeike.Results.MinimalApi
Return Toarnbeike.Results from your AspNetCore Minimal Api Endpoints |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.0.0 | 244 | 8/28/2025 |