Toarnbeike.Results
2.1.0
dotnet add package Toarnbeike.Results --version 2.1.0
NuGet\Install-Package Toarnbeike.Results -Version 2.1.0
<PackageReference Include="Toarnbeike.Results" Version="2.1.0" />
<PackageVersion Include="Toarnbeike.Results" Version="2.1.0" />
<PackageReference Include="Toarnbeike.Results" />
paket add Toarnbeike.Results --version 2.1.0
#r "nuget: Toarnbeike.Results, 2.1.0"
#:package Toarnbeike.Results@2.1.0
#addin nuget:?package=Toarnbeike.Results&version=2.1.0
#tool nuget:?package=Toarnbeike.Results&version=2.1.0
Toarnbeike.Results
This package provides a lightweight, functional-style result abstraction for explicit error handling in .NET.
It introduces Result and Result<TValue> types, inspired by functional programming
and discriminated unions, while remaining idiomatic to the .NET ecosystem.
A Result represents an outcome of an operation, which can either be a Success, or a Failure.
The success path can contain a value, represented by Result<TValue>, where TValue is the inner value.
The failure path contains failure information, modelled as an Failure record.
Using results 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 async support: Works naturally with Task and async pipelines.
- Functional programming inspired: Inspired by FP principles for predictable, readable, and maintainable error handling.
Contents
- Quick start
- Core concepts
- Extensions
- Collections
- LINQ Query syntax support
- Test extensions
- Packages
- Inspiration
- Conclusion
Quick start
This example demonstrates the most common workflow when using results: construction, transformation and consumption.
using Toarnbeike.Results; // Base namespace for Result, Result<TValue> and Failure
using Toarnbeike.Results.Extensions; // For functional extensions on Result and Result<TValue>
A result can represent either success (with or without a value) or failure (with error details):
// Success Results
Result<int> result = 42;
Result<int> failureResult = new Failure("Code", "Something went wrong");
// Transform a result
var mapped = result.Map(val => $"success: {val}"); // Mapped to Result<string>
var binded = failureResult.Bind(val => BindValue(val)); // Remains a failure.
// Consume the result
var matched = mapped.Match(val => val, _ => "A failure occurred");
Console.WriteLine(matched); // Output: success: 42
if (binded.TryGetFailure(out var failure))
{
Console.WriteLine(failure.Message); // Output: Something went wrong
}
Core concepts
What is a Result?
A result represents one of two possible states, either a success or a failure. At any point, the result is either in a success state or in a failure state.
What is a Failure?
A failure is a state of the Result, which is represented by a Failure record.
This record has at least the Message and FailureCategory properties, for human readable information
about what caused the failure.
The Failure record is abstract, an some concrete failure types are already provided.
It is encouraged to create specific failure types for e.g. business related failures.
For the more details regarding failures and the already provided failure overloads, see Failures
What is a Result<TValue>?
A Result<TValue> is a result which carries a payload, the TValue, if the result is a success.
Construction
Results can be constructed either by using the static factory methods, or using implicit conversion from a value or a failure.
var a = Result.Success(); // Result, state: success
var b = Result.Failure(failure); // Result, state: failure
var c = Result<int>.Success(42); // Result<int>, state: success, value: 42
var d = Result<int>.Failure(failure); // Result<int>, state: failure
Result e = failure; // Result, state: failure
Result<int> f = 42; // Result<int>, state: success, value: 42
Result<int> g = failure; // Result<int>, state: failure
Transformations
Results can be transformed on value using the many provided extension methods. For an overview of the available methods, see Extension methods. For a detailed description of each of the methods, see Extension documentation.
Consumption
Results can be consumed either by
- using the Match extension method which requires a delegate for both the success state as the failure state.
- using the TryGet methods, either to get the value if a success or the failure if a failure.
var output = result.Match(
onSuccess: value => $"success: {value}",
onFailure: failure => failure.Message
);
Console.WriteLine(output); // Output: success: 42
if (g.TryGetFailure(out var failure))
{
// do something with the failure.
}
Extensions
The Toarnbeike.Results.Extensions namespace includes rich extensions for Result and Result<TValue>:
| Method | Result |
Result<T> |
Description |
|---|---|---|---|
Bind(...) |
[x] | [x] | Chains operations returning Result<TOut> |
Map(...) |
[ ] | [x] | Transforms the success value |
Tap(...) |
[x] | [x] | Executes side-effects on success |
TapFailure(...) |
[x] | [x] | Executes side-effects on failure |
BindTap(...) |
[x] | [x] | Chains a result operation without changing value |
Combine(...) |
[ ] | [x] | Combines two results into a new value |
CombineBind(...) |
[ ] | [x] | Combines two results into a new result |
WithValue(...) |
[x] | [ ] | Converts to Result<TValue> with a value |
TryGetValue(...) |
[ ] | [x] | Gets the success value if available |
TryGetFailure(...) |
[x] | [x] | Gets the failure if present |
Match(...) |
[x] | [x] | Maps success or failure to a value |
All methods support async variants and operate seamlessly with Task<Result<TValue>>.
For information per method see the Extensions docs.
Collections
The Toarnbeike.Results.Collections namespace provides extension methods for working with collections of results:
| Method | Result |
Result<T> |
Description |
|---|---|---|---|
Aggregate(...) |
[x] | [x] | Collects all successes or all failures |
Sequence(...) |
[ ] | [x] | Collects successes or returns first failure |
AllSuccess(...) |
[x] | [x] | Checks if all results are successful |
Failures(...) |
[x] | [x] | Extracts all failures |
SuccessValues(...) |
[ ] | [x] | Extracts all success values |
Split(...) |
[ ] | [x] | Splits results into successes and failures |
All methods support async variants and operate seamlessly with IEnumerable<Task<Result<TValue>>>.
For information per method see the Collections docs.
LINQ Query syntax support
Toarnbeike.Results supports C# LINQ query syntax for composing Result<TValue> pipelines using from, select, let, and where.
This provides an alternative, declarative way to compose Bind, Map, and BindTap operations while preserving the same failure propagation semantics.
Failures are automatically propagated and short-circuit execution of the query.
See the LINQ extensions docs for details and examples.
Test Extensions
Toarnbeike.Results provides optional test extensions for verifying Result and Result<TValue> instances in unit tests.
These extensions offer a minimal set of assertions for checking success and failure outcomes, including typed failure assertions.
See the Test extensions docs for details and examples.
Packages
The Toarnbeike.Results ecosystem consist of a couple of packages:
| Package | Description | NuGet |
|---|---|---|
Toarnbeike.Results |
Core result type, extension methods and collections | |
Toarnbeike.Results.Abstractions |
Abstractions, as netstandard2.0 project for sourceGen | |
Toarnbeike.Results.FluentValidation |
Validation integration using FluentValidation |
|
Toarnbeike.Results.MinimalApi |
Integration with Microsoft.AspNetCore minimal API's |
|
Toarnbeike.Results.Ensure |
Domain validation using Ensure pipelines |
Inspiration
This project draws inspiration from:
Conclusion
Exceptions should be exceptional. Results give you clarity, safety, and composability without relying on exceptions for control flow.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- Toarnbeike.Results.Abstractions (>= 2.1.0)
NuGet packages (5)
Showing the top 5 NuGet packages that depend on Toarnbeike.Results:
| Package | Downloads |
|---|---|
|
Toarnbeike.Results.FluentValidation
Integrating FluentValidation with Toarnbeike.Results |
|
|
Toarnbeike.Results.MinimalApi
Return Toarnbeike.Results from your AspNetCore Minimal Api Endpoints |
|
|
Toarnbeike.Results.Optional
Convert between Toarnbeike.Results an Toarnbeike.Optional |
|
|
Toarnbeike.Dispatch
lightweight dispatching framework for result driven requests and notifications |
|
|
Toarnbeike.Results.Ensure
Composable guard library that enables clean, fail-fast domain validation without exceptions. |
GitHub repositories
This package is not used by any popular GitHub repositories.