Outcome 1.0.0
dotnet add package Outcome --version 1.0.0
NuGet\Install-Package Outcome -Version 1.0.0
<PackageReference Include="Outcome" Version="1.0.0" />
<PackageVersion Include="Outcome" Version="1.0.0" />
<PackageReference Include="Outcome" />
paket add Outcome --version 1.0.0
#r "nuget: Outcome, 1.0.0"
#:package Outcome@1.0.0
#addin nuget:?package=Outcome&version=1.0.0
#tool nuget:?package=Outcome&version=1.0.0
Outcome
Result types with closed type hierarchies for type-safe error handling without exceptions, and exhaustive pattern matching.
What it does
This library implements the Railway Oriented Programming pattern with Result types that force explicit error handling. A Result represents either success (Ok) or failure (Error), eliminating null checks and exception handling. When used with the Exhaustion analyzer, switches have exhaustive pattern matching checks.
Features
- Type-safe error handling without exceptions
- Exhaustive pattern matching with closed type hierarchies
- Monadic operations (Map, Bind, Match)
- Sequence/traverse for collections
- Works with the Exhaustion analyzer for compile-time exhaustiveness checking
Installation
dotnet add package Outcome
Examples
Basic Usage
using Outcome;
// Create results
Result<int, string> success = new Result<int, string>.Ok<int, string>(42);
Result<int, string> failure = Result<int, string>.Failure("Something went wrong");
// Pattern matching (exhaustive with Exhaustion analyzer)
var message = result switch
{
Result<int, string>.Ok(var value) => $"Success: {value}",
Result<int, string>.Error(var error) => $"Error: {error}"
};
Functional Composition
// Map transforms success values
Result<int, string> GetUserId() => new Result<int, string>.Ok<int, string>(123);
var userAge = GetUserId()
.Map(id => id * 2)
.Map(id => $"User age: {id}");
// Bind chains operations that return Results
Result<User, string> GetUser(int id) => /* ... */;
Result<Order[], string> GetOrders(User user) => /* ... */;
var orders = GetUserId()
.Bind(GetUser)
.Bind(GetOrders);
Error Handling
// Match handles both cases
var output = result.Match(
onSuccess: value => $"Got {value}",
onError: error => $"Failed: {error}"
);
// GetValueOrDefault provides fallbacks
var value = result.GetValueOrDefault(0);
// Tap performs side effects without changing the result
result.Tap(
onSuccess: v => Console.WriteLine($"Success: {v}"),
onError: e => Console.WriteLine($"Error: {e}")
);
Collections
// Sequence converts List<Result<T, E>> to Result<List<T>, E>
// Returns first error or all successes
var results = new[] { result1, result2, result3 };
Result<IReadOnlyList<int>, string> combined = results.Sequence();
HttpError Types
The library includes specialized error types for HTTP scenarios:
// HttpError<TError> represents HTTP-specific failures
public abstract record HttpError<TError>
{
public sealed record ExceptionError(Exception Exception) : HttpError<TError>;
public sealed record ErrorResponseError(TError Body, int StatusCode) : HttpError<TError>;
}
// Usage with RestClient.Net
Result<User, HttpError<ApiError>> result = await client.GetAsync<User, ApiError>(...);
var message = result switch
{
Result<User, HttpError<ApiError>>.Ok(var user) => $"User: {user.Name}",
Result<User, HttpError<ApiError>>.Error(HttpError<ApiError>.ExceptionError(var ex)) =>
$"Exception: {ex.Message}",
Result<User, HttpError<ApiError>>.Error(HttpError<ApiError>.ErrorResponseError(var body, var status)) =>
$"HTTP {status}: {body.Message}"
};
Why Use Results?
- No null reference exceptions: Errors are explicit values
- No uncaught exceptions: All errors are handled or propagated as values
- Compiler-enforced error handling: Can't ignore errors
- Composable: Chain operations with Map/Bind
- Exhaustive: Works with Exhaustion analyzer for complete pattern matching
| Product | Versions 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 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. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Outcome:
| Package | Downloads |
|---|---|
|
RestClient.Net
The safest way to make REST calls in C#. Functional HTTP client library with Result types, exhaustiveness checking, and zero exceptions. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 619 | 10/13/2025 |
Initial release of the Results library extracted from RestClient.Net.