Toarnbeike.Results 2.1.0

dotnet add package Toarnbeike.Results --version 2.1.0
                    
NuGet\Install-Package Toarnbeike.Results -Version 2.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Toarnbeike.Results" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Toarnbeike.Results" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Toarnbeike.Results" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Toarnbeike.Results --version 2.1.0
                    
#r "nuget: Toarnbeike.Results, 2.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Toarnbeike.Results@2.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Toarnbeike.Results&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Toarnbeike.Results&version=2.1.0
                    
Install as a Cake Tool

CI .NET 10 License: MIT

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

  1. Quick start
  2. Core concepts
  3. Extensions
  4. Collections
  5. LINQ Query syntax support
  6. Test extensions
  7. Packages
  8. Inspiration
  9. 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 NuGet
Toarnbeike.Results.Abstractions Abstractions, as netstandard2.0 project for sourceGen NuGet
Toarnbeike.Results.FluentValidation Validation integration using FluentValidation NuGet
Toarnbeike.Results.MinimalApi Integration with Microsoft.AspNetCore minimal API's NuGet
Toarnbeike.Results.Ensure Domain validation using Ensure pipelines NuGet

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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.