Trellis.Results 3.0.0-alpha.127

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

Railway Oriented Programming

NuGet Package

Composable error handling for .NET using Result<T>, Maybe<T>, and 10 discriminated error types. No exceptions, no null — just clean pipelines that read like English.

Installation

dotnet add package Trellis.Results

Quick Start

using Trellis;

// Chain operations — errors short-circuit automatically
Result<string> result = GetUser(userId)
    .Ensure(user => user.IsActive, Error.Validation("User is not active"))
    .Tap(user => _logger.LogInformation("Accessed {Id}", user.Id))
    .Map(user => user.Email);

// Pattern match the result
result.Match(
    onSuccess: email => Console.WriteLine($"Email: {email}"),
    onFailure: error => Console.WriteLine($"Error: {error.Detail}")
);

Core Types

Result<T>

Represents success (with a value) or failure (with an error).

Result<int> success = 42;                                    // Implicit conversion
Result<int> failure = Error.NotFound("Item not found");      // Implicit conversion

if (success.IsSuccess)
    Console.WriteLine(success.Value);  // 42

Maybe<T>

Domain-level optionality — replaces nullable references.

Maybe<string> some = Maybe.From("hello");
Maybe<string> none = Maybe.None<string>();

string greeting = some.Match(
    s => $"Hi, {s}!",
    () => "No name");

Error Types

Error Type Factory HTTP Status
ValidationError Error.Validation() 400
BadRequestError Error.BadRequest() 400
UnauthorizedError Error.Unauthorized() 401
ForbiddenError Error.Forbidden() 403
NotFoundError Error.NotFound() 404
ConflictError Error.Conflict() 409
DomainError Error.Domain() 422
RateLimitError Error.RateLimit() 429
UnexpectedError Error.Unexpected() 500
ServiceUnavailableError Error.ServiceUnavailable() 503

Pipeline Operations

Method Purpose Example
Bind Chain operations that return Result .Bind(user => GetOrder(user.Id))
Map Transform value, keep Result wrapper .Map(user => user.Email)
Tap Side effects on success .Tap(user => Log(user.Id))
TapOnFailure Side effects on failure .TapOnFailure(err => Log(err))
Ensure Validate conditions .Ensure(u => u.IsActive, error)
EnsureAll Validate all, accumulate errors .EnsureAll((u => u.IsActive, err1), ...)
Match Pattern match success/failure .Match(onSuccess, onFailure)
MatchError Pattern match on specific error types .MatchError(onSuccess, onNotFound, ...)
Combine Merge multiple Results Result.Combine(r1, r2, r3)
Recover Simple fallback on failure .Recover(defaultValue)
RecoverOnFailure Fallback on failure .RecoverOnFailure(err => default)
ToMaybe Convert Result to Maybe .ToMaybe() — success→Some, failure→None
MapOnFailure Transform errors .MapOnFailure(err => Error.Domain(...))
When Conditional operations .When(u => u.IsPremium, ApplyDiscount)
Traverse Map collection, short-circuit on first failure items.Traverse(i => Validate(i))

All operations have async variants (BindAsync, MapAsync, etc.) with CancellationToken support. LINQ query syntax is also supported (from, select, where) for both Result<T> and Maybe<T>.

Real-World Example

public Result<Order> PlaceOrder(OrderRequest request)
{
    return ProductId.TryCreate(request.ProductId)
        .Combine(Quantity.TryCreate(request.Quantity))
        .Bind((productId, qty) => _inventory.Reserve(productId, qty))
        .Ensure(reservation => reservation.IsConfirmed, 
            Error.Conflict("Item is out of stock"))
        .Map(reservation => Order.FromReservation(reservation))
        .Tap(order => _events.Publish(new OrderPlaced(order.Id)));
}

Combine — Collect All Errors

// Validates ALL fields and returns ALL errors at once
var result = FirstName.TryCreate(input.FirstName)
    .Combine(LastName.TryCreate(input.LastName))
    .Combine(EmailAddress.TryCreate(input.Email))
    .Bind((first, last, email) => User.TryCreate(first, last, email));

Performance

11–16 nanoseconds per operation — 0.002% of a typical database query. Zero extra allocations on Combine.

License

MIT — see LICENSE for details.

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 (10)

Showing the top 5 NuGet packages that depend on Trellis.Results:

Package Downloads
Trellis.DomainDrivenDesign

Building blocks for implementing Domain-Driven Design tactical patterns in C# with functional programming principles. Create Aggregate, Entity, and ValueObject classes with Result-based validation. For simple value objects with a single value, ScalarValueObject can be used. For strongly-typed primitives, see Trellis.Primitives.

Trellis.Primitives

Infrastructure and ready-to-use implementations for primitive value objects in Domain-Driven Design. Includes base classes (RequiredString, RequiredGuid) with source generation, plus EmailAddress with RFC 5322 validation. Eliminates primitive obsession with strongly-typed domain primitives.

Trellis.Asp

These extension methods are used to convert the ROP Result object to ActionResult. If the Result is in a failed state, it returns the corresponding HTTP error code.

Trellis.Testing

Testing utilities and assertions for Trellis - FluentAssertions extensions, test builders, and fake implementations for Railway-Oriented Programming

Trellis.Stateless

Wraps the Stateless library's Fire() method to return Result instead of throwing on invalid transitions, converting known invalid-transition exceptions into failure results for Railway Oriented Programming.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0-alpha.127 31 3/23/2026
3.0.0-alpha.123 49 3/19/2026
3.0.0-alpha.118 59 3/14/2026
3.0.0-alpha.111 57 3/12/2026
3.0.0-alpha.104 78 3/9/2026
3.0.0-alpha.100 57 3/4/2026
3.0.0-alpha.99 47 3/4/2026
3.0.0-alpha.98 45 3/3/2026
3.0.0-alpha.95 50 3/2/2026
3.0.0-alpha.94 56 3/2/2026
3.0.0-alpha.93 59 3/1/2026
3.0.0-alpha.92 67 2/28/2026
3.0.0-alpha.83 60 2/27/2026