ForgeSharp.Results 2.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package ForgeSharp.Results --version 2.2.0
                    
NuGet\Install-Package ForgeSharp.Results -Version 2.2.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="ForgeSharp.Results" Version="2.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ForgeSharp.Results" Version="2.2.0" />
                    
Directory.Packages.props
<PackageReference Include="ForgeSharp.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 ForgeSharp.Results --version 2.2.0
                    
#r "nuget: ForgeSharp.Results, 2.2.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 ForgeSharp.Results@2.2.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=ForgeSharp.Results&version=2.2.0
                    
Install as a Cake Addin
#tool nuget:?package=ForgeSharp.Results&version=2.2.0
                    
Install as a Cake Tool

ForgeSharp.Results

A monadic Result type for .NET that replaces exceptions as flow control with explicit, composable success/failure values. All core types are readonly struct — zero heap allocations, zero GC pressure.

Target Supported
.NET 10 Yes
.NET 8 Yes
.NET Standard 2.1 Yes
.NET Standard 2.0 Yes

Install

dotnet add package ForgeSharp.Results

Get started

Return a Result from any operation. Check IsSuccess to branch on the outcome — no try/catch required.

Result<User> GetUser(int id)
{
    var user = db.Find(id);
    return user is not null
        ? Result.Ok(user)
        : Result.Fail<User>("User not found.");
}

var result = GetUser(42);
if (result.IsSuccess)
    Console.WriteLine(result.Value.Name);
else
    Console.WriteLine(result.Message);

Chain operations with Map and Bind. Failures propagate automatically — no manual error checking between steps.

var result = GetUser(42)
    .Bind(user => Validate(user))
    .Map(user => user.Profile);

Wrap code that throws into a Result with Capture:

Result result = Result.Capture(() => RiskyOperation());
Result<int> parsed = Result.Capture(() => int.Parse(input));

// Async
Result<Data> data = await Result.CaptureAsync(() => httpClient.GetFromJsonAsync<Data>(url));

Core types

Type Description
Result Non-generic success/failure.
Result<T> Carries a T value on success.
Result<TValue, TError> Discriminated result with a custom error type.
Options<T> Optional value wrapper (Some / None).
EnumerableResult / EnumerableResult<T> Aggregated batch results with counts, ratios, and filtering.

Results distinguish three states: success, validation fault (with a message), and exception (with a captured Exception). The IsSuccess, IsValidationFault, and IsException properties let you branch accordingly.

Pipelines

Pipelines compose result-producing operations into discrete, reusable units. They come in sync (IPipeline<T>) and async (IAsyncPipeline<T>) variants and support LINQ query syntax.

var pipeline =
    from user in GetUserPipeline()
    where user.IsActive
    from profile in GetProfilePipeline(user.Id)
    select (user, profile);

Result<(User user, Profile profile)> result = pipeline.Execute();

Pipelines also support retry and timeout policies:

var resilient = Pipeline.Create(() => CallExternalService())
    .Retry(3, TimeSpan.FromSeconds(1))
    .Timeout(TimeSpan.FromSeconds(10));

Result result = resilient.Execute();

Use Repeat to execute a pipeline multiple times and collect the results:

EnumerableResult batch = pipeline.Repeat(100).ToEnumerableResult();
Console.WriteLine($"{batch.SuccessPercentage}% succeeded");

Extension methods

Every extension ships with an async counterpart (e.g. Map / MapAsync).

Chaining

Method Purpose
Map Transform the value if successful.
Bind FlatMap — chain an operation that itself returns a Result.
Select Project the value to a new type.
Flatten Unwrap a nested Result<Result<T>>.
var name = GetUser(42)
    .Bind(u => LoadSettings(u.Id))
    .Map(s => s.DisplayName)
    .GetOrDefault("Unknown");

Side effects

Method Purpose
Tap Execute an action on success without changing the result.
TapError Execute an action on failure without changing the result — great for logging.
Restore Recover from a failure with a fallback function.
var result = GetUser(42)
    .Tap(user => Log.Info($"Found {user.Name}"))
    .TapError(err => Log.Warn($"Lookup failed: {err.Message}"));

Error transformation

Method Purpose
MapError Transform the error of a Result<TValue, TError> while preserving the value.
Result<User, ApiError> apiResult = CallApi();
Result<User, string> friendly = apiResult.MapError(e => e.UserMessage);

Value extraction

Method Purpose
GetOrDefault Returns the value, or a fallback if failed.
GetOrThrow Returns the value, or re-throws the captured exception.
EnsureNotNull Converts a Result<T?> to Result<T>, failing on null.
AsResult Drops the value, converting Result<T> to Result.
TryGetValue Try-pattern extraction (bool + out T).
ToOption Converts a result to Options<T>Some on success, None on failure.

Collections

Method Purpose
TryGetValueResult Dictionary lookup that returns Result<T> instead of bool.
FirstOrResult First matching element, or a failure with a message.
ResolveAsync Awaits a collection of Task<Result<T>> into aggregated results.
FilterValues / FilterExceptions Extract successes or failures from an EnumerableResult<T>.
AggregateValidation Combines all validation messages into a single result.
ExtractValuesOrDefault All values from a batch, substituting a default for failures.

Options interop

Convert freely between Options<T> and Result<T>:

// Result → Option
Options<User> maybeUser = GetUser(42).ToOption();

// Option → Result
Result<User> result = maybeUser.ToResult("No user found.");

// With a discriminated error type
Result<User, MyError> typed = maybeUser.ToResult(new MyError("missing"));

I/O integration

File, directory, and HTTP operations are wrapped as Result-returning extension methods so you never need a try/catch around I/O.

File & directory

Result<FileStream> stream = new FileInfo("data.bin").OpenReadAsResult();
Result deleted = File.DeleteAsResult("temp.log");

Result<DirectoryInfo> dir = Directory.CreateAsResult(@"C:\App\Logs");
Result removed = new DirectoryInfo(@"C:\App\Old").DeleteAsResult();

HttpClient

Every HTTP verb has an AsResult variant:

Result<HttpResponseMessage> response = await httpClient.GetAsResultAsync("https://api.example.com/items");

Result<Item[]> items = await httpClient
    .GetAsResultAsync("https://api.example.com/items")
    .ThenEnsureSuccessStatusCodeAsync(
        success: r => r.Content.ReadFromJsonAsync<Item[]>(),
        failure: r => $"API returned {r.StatusCode}");

API reference

Area Key types / methods
Core Result, Result<T>, Result<TValue, TError>, Options<T>
Pipelines IPipeline<T>, IAsyncPipeline<T>, Pipeline.Create(...)
Monad Map, MapError, Bind, Select, Flatten, Tap, TapError, Restore, Retry, Timeout, Repeat
Extraction GetOrDefault, GetOrThrow, EnsureNotNull, AsResult, TryGetValue, ToOption, ToResult
Collections EnumerableResult<T>, TryGetValueResult, FirstOrResult, ResolveAsync, AggregateValidation
Integration OpenReadAsResult, DeleteAsResult, CreateAsResult, SendAsResultAsync, ThenEnsureSuccessStatusCode
LINQ from/where/select query syntax on pipelines

Contributing

Contributions are welcome. Open an issue or submit a pull request on GitHub.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  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 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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on ForgeSharp.Results:

Package Downloads
ForgeSharp.Results.AspNetCore

AspNetCore Integration for ForgeSharp.Results.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.2.1 341 4/23/2026
2.2.0 174 3/24/2026
2.1.0 126 3/4/2026
2.0.0 117 3/2/2026
1.2.1 276 1/19/2026
1.2.0 129 1/18/2026
1.1.0 408 7/20/2025
1.0.0 154 7/12/2025