Spirantis.Result 10.0.0

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

Spirantis.Result

A small, dependency-free result type for C#. Model the outcome of an operation as an explicit success or failure instead of throwing, with a lightweight functional API (Match, Map, Bind, Tap) for composing the happy path.

  • Result — success/failure with an optional Error.
  • Result<T> — success carries a value of type T; failure carries an Error.
  • Error — a failure reason: a Message and an optional wrapped Exception.

Targets .NET 10. No runtime dependencies. MIT licensed.

Install

dotnet add package Spirantis.Result

Quick start

using Spirantis.Result;

Result<int> Parse(string input) =>
    int.TryParse(input, out var n)
        ? n                              // implicit: value  -> success
        : new Error("not a number");     // implicit: error  -> failure

string message = Parse("41")
    .Map(n => n + 1)                     // 42, still success
    .Match(
        onSuccess: n => $"got {n}",
        onFailure: e => $"failed: {e?.Message}");
// "got 42"

Creating results

Use the implicit conversions or the static factories — whichever reads better.

// Result (no value)
Result ok   = Result.Success();
Result bad  = Result.Fail("disk full");
Result wrap = new InvalidOperationException("boom");   // implicit -> failure

// Result<T>
Result<int> value = 42;                  // implicit -> success
Result<int> error = new Error("nope");   // implicit -> failure
Result<int> viaFactory = Result.Fail<int>("nope");
Result<User> user = Result.Success(new User());

Note: on Result<T>, only T (success) and Error (failure) convert implicitly. Unlike the non-generic Result, there is intentionally no implicit string/Exception conversion — it would be ambiguous for Result<string>/Result<Exception>. Use Result.Fail<T>(...) for those.

Inspecting results

if (result.IsSuccess) { /* ... */ }
if (result.IsFailure) { /* ... */ }

// Result<T>: TryGetValue narrows nullability for you
if (result.TryGetValue(out var value))
    Console.WriteLine(value);            // value is non-null here

if (!result.TryGetValue(out var value, out var error))
    Console.WriteLine(error?.Message);

int safe        = result.GetValueOr(-1);
int? maybe      = result.GetValueOrDefault();

IsSuccess on Result<T> is annotated with [MemberNotNullWhen(true, nameof(Value))], so the compiler knows Value is non-null inside an if (result.IsSuccess) branch.

Composing

Method On Behaviour
Match Result, Result<T> Fold to a single value via onSuccess / onFailure.
Map Result<T> Transform the value on success; propagate the failure otherwise.
Bind Result<T> Chain another Result<T>-producing step; short-circuits on failure.
Tap Result<T> Run a side effect on the value when successful; returns the same result.
OnSuccess / OnFailure Result Run a side effect for the matching branch; returns the same result.
Result<string> outcome = LoadUser(id)            // Result<User>
    .Tap(u => logger.LogInformation("loaded {Id}", u.Id))
    .Bind(u => Authorize(u))                      // Result<Session>
    .Map(s => s.Token);                           // Result<string>

The onFailure delegate receives Error? (nullable): a failure produced by Result.Fail() has no associated error.

Errors

var fromMessage   = new Error("validation failed");
var fromException = new Error(ex);                 // Message defaults to ex.Message
var withBoth      = new Error(ex, "friendly text");

Error implicitMsg = "shorthand";                   // implicit

Error is immutable and has value equality: two errors are equal when their Message matches and they reference the same Exception instance (exceptions compare by reference).

Equality

Result, Result<T>, and Error all implement value equality (Equals / GetHashCode), which makes them easy to assert in tests:

Assert.Equal(Result.Success(42), Result.Success(42));
Assert.Equal(Result.Fail<int>("x"), Result.Fail<int>("x"));

Results of different runtime types are never equal (e.g. Result<int>Result<long>).

Extending

Result / Result<T> are open for inheritance — derive when you need extra state. Override the protected EqualsCore hook to fold that state into equality:

public class FunctionResult : Result<object>
{
    public FunctionResult(FunctionResultType type, object value) : base(value) => Type = type;
    public FunctionResultType Type { get; init; }

    protected override bool EqualsCore(Result other) =>
        base.EqualsCore(other) && Type == ((FunctionResult)other).Type;
}

License

MIT

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.
  • net10.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Spirantis.Result:

Package Downloads
Spirantis.Sequencing.Abstraction

Abstractions (ISequenceFunction, FunctionResult, ISequenceContext) for Spirantis.Sequencing — a fluent engine for composing asynchronous, branching workflows.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.0 135 6/8/2026