FluentUnions.AwesomeAssertions 2.1.0

dotnet add package FluentUnions.AwesomeAssertions --version 2.1.0
                    
NuGet\Install-Package FluentUnions.AwesomeAssertions -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="FluentUnions.AwesomeAssertions" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FluentUnions.AwesomeAssertions" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="FluentUnions.AwesomeAssertions" />
                    
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 FluentUnions.AwesomeAssertions --version 2.1.0
                    
#r "nuget: FluentUnions.AwesomeAssertions, 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 FluentUnions.AwesomeAssertions@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=FluentUnions.AwesomeAssertions&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=FluentUnions.AwesomeAssertions&version=2.1.0
                    
Install as a Cake Tool

FluentUnions

FluentUnions

NuGet Downloads License: MIT GitHub

Comprehensive discriminated unions for C#/.NET: Result<T> and Result for explicit error handling, Option<T> for null safety. Features fluent API, static analyzers, and zero-allocation performance.

Table of contents

Why FluentUnions

  • True discriminated unions: Type-safe Result<T>, Result, and Option<T> with exhaustive matching
  • Explicit error handling: No hidden exceptions for expected failures
  • Null safety: Option<T> eliminates null reference exceptions
  • Fluent operations: Chain with Map, Bind, Match, Ensure, and more
  • Zero allocations: Struct-based abstractions, optimized for performance
  • Static analysis: Roslyn analyzers prevent common mistakes at compile-time
  • Rich error types: Built-in validation, conflict, authentication errors with metadata
  • Error accumulation: Collect all errors or fail-fast strategies
  • AOT-friendly: Full AOT compatibility, no runtime code emission

Install

dotnet add package FluentUnions

For test assertions with AwesomeAssertions:

dotnet add package FluentUnions.AwesomeAssertions

Quick tour

Result - Error handling

// Methods that can fail return Result<T>
public Result<User> GetUser(int id)
{
    if (id <= 0)
        return new ValidationError("Invalid user ID");

    var user = database.FindUser(id);
    if (user == null)
        return new NotFoundError($"User {id} not found");

    return user; // Implicit conversion from T to Result<T>
}

// Chain operations
var greeting = GetUser(123)
    .Map(user => user.Name)
    .Match(
        success: name => $"Hello, {name}!",
        failure: error => $"Error: {error.Message}"
    );

Option - Null safety

// Replace nulls with Option<T>
public Option<string> GetMiddleName(User user)
{
    return user.MiddleName.AsOption(); // null becomes None
}

// Safe chaining
var displayName = GetUser(123)
    .ToOption()
    .Bind(user => GetMiddleName(user))
    .Map(name => name.ToUpper())
    .Match(
        some: name => name,
        none: () => "N/A"
    );

Validation with built-in methods

// Fluent validation
public Result<string> ValidateEmail(string email)
{
    return Result.For(email)
        .Ensure.NotEmpty()
        .Ensure.Matches(@"^[^@]+@[^@]+\.[^@]+$")
        .Ensure.ShorterThan(255);
}

// Accumulate all errors
public Result<User> CreateUser(string email, string password, int age)
{
    return Result.BindAllAppend(
        Result.For(email)
            .Ensure.NotEmpty()
            .Ensure.Matches(@"^[^@]+@[^@]+\.[^@]+$"),
        Result.For(password)
            .Ensure.LongerThanOrEqualTo(8)
            .Ensure.Matches(@"[A-Z]", "Must contain uppercase"),
        Result.For(age)
            .Ensure.GreaterThanOrEqualTo(18))
        .Map((email, password, age) => new User(email, password, age));
}

Static analyzers

Roslyn analyzers catch mistakes at compile-time:

// ⚠️ FU0001: Accessing Value without checking IsSome
Option<int> option = GetOption();
var value = option.Value; // Analyzer warning!

// ✅ Safe access
if (option.IsSome)
{
    var value = option.Value; // OK
}

// ⚠️ FU0101: Accessing Value without checking IsSuccess
Result<string> result = GetResult();
var data = result.Value; // Analyzer warning!

// ✅ Better: Use Match
var data = result.Match(
    success: value => value,
    failure: error => "default"
);

Core types

Discriminated unions

  • Result<T>: Success(T value) | Failure(Error error)
  • Result: Success | Failure(Error error)
  • Option<T>: Some(T value) | None

Error types

  • ValidationError - Input validation failures
  • NotFoundError - Resource not found
  • ConflictError - Business rule conflicts
  • AuthenticationError - Authentication failures
  • AuthorizationError - Authorization failures
  • CompositeError - Multiple errors combined
  • ErrorWithMetadata - Errors with additional context

Error strategies

  • Short-circuit: Stop at first error (Bind, Ensure)
  • Accumulate: Collect all errors (BindAll, EnsureAll)

Documentation

This README stays intentionally brief. Full documentation lives in the docs:

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

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 76 8/15/2025