RustlikeValues.Result 2.0.0

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

RustLike Result<T, E> for C#

A robust implementation of Rust's Result type for C#, providing elegant error handling without exceptions.

Installation

dotnet add package RustLikeValues.Result

Overview

The Result<T, E> type represents either success (Ok) containing a value of type T, or failure (Err) containing an error of type E. This pattern enables explicit error handling, making your code more predictable and easier to reason about.

Key Features

  • Explicit Error Handling: Makes error cases visible in method signatures
  • Chainable Operations: Supports functional programming patterns with Map, AndThen, etc.
  • Pattern Matching: Use C# pattern matching or built-in Match methods
  • JSON Serialization: Built-in support for System.Text.Json
  • Zero Overhead: Struct-based implementation for optimal performance
  • Async Support: Full async/await compatibility

Quick Start

using RustLikeValues.RustLikeResult;

// Creating Results
var success = Result.Ok(42);
var failure = Result.Err("Something went wrong");

// Using explicit types when needed
var typedResult = Result<int, string>.Ok(42);

// Pattern matching
var message = result.Match(
    Ok: value => $"Success: {value}",
    Err: error => $"Error: {error}"
);

// Chaining operations
var final = await GetUserAsync(id)
    .MapAsync(user => enrichUserDataAsync(user))
    .AndThen(user => ValidateUser(user))
    .MapErr(err => $"Failed to process user: {err}")
    .UnwrapOr(DefaultUser);

Core Methods

Creation

  • Result.Ok<T>(value) - Creates a success result
  • Result.Err<E>(error) - Creates an error result
  • Result<T,E>.Ok(value) - Type-specific success
  • Result<T,E>.Err(error) - Type-specific error

Checking State

  • IsOk - Returns true if the result is Ok
  • IsErr - Returns true if the result is Err

Extracting Values

  • Unwrap() - Gets the Ok value or throws
  • UnwrapOr(defaultValue) - Gets the Ok value or returns default
  • UnwrapOrElse(Func<E, T>) - Gets the Ok value or computes from error
  • UnwrapErr() - Gets the Err value or throws

Transforming

  • Map<U>(Func<T, U>) - Transform Ok value
  • MapErr<F>(Func<E, F>) - Transform Err value
  • AndThen<U>(Func<T, Result<U, E>>) - Chain operations that return Result

Pattern Matching

  • Match<U>(Func<T, U> Ok, Func<E, U> Err) - Transform to a single type
  • Match(Action<T> Ok, Action<E> Err) - Execute side effects

Common Patterns

Error Propagation

public Result<Order, string> ProcessOrder(int orderId)
{
    return GetOrder(orderId)
        .AndThen(order => ValidateOrder(order))
        .AndThen(order => CalculateTotal(order))
        .Map(order => ApplyDiscounts(order));
}

Try-Catch Replacement

public Result<Data, Exception> LoadData(string path)
{
    try
    {
        var data = File.ReadAllText(path);
        return Result.Ok(JsonSerializer.Deserialize<Data>(data));
    }
    catch (Exception ex)
    {
        return Result.Err(ex);
    }
}

Async Operations

public async Task<Result<User, ApiError>> GetUserAsync(int id)
{
    var response = await httpClient.GetAsync($"/users/{id}");
    
    if (!response.IsSuccessStatusCode)
        return Result.Err(new ApiError(response.StatusCode));
    
    var user = await response.Content.ReadFromJsonAsync<User>();
    return Result.Ok(user);
}

Validation Chain

public Result<User, ValidationError> ValidateUser(User user)
{
    return ValidateName(user.Name)
        .AndThen(_ => ValidateEmail(user.Email))
        .AndThen(_ => ValidateAge(user.Age))
        .Map(_ => user);
}

Advanced Features

Implicit Conversions

// Use OkValue and ErrValue for cleaner syntax
Result<int, string> result = Result.Ok(42);  // Implicitly converts
Result<int, string> error = Result.Err("failed");  // Implicitly converts

Deconstruction

var (isOk, value, error) = result;
if (isOk)
    Console.WriteLine($"Value: {value}");
else
    Console.WriteLine($"Error: {error}");

JSON Serialization

var result = Result.Ok<int, string>(42);
var json = JsonSerializer.Serialize(result);
// Output: {"$type":"ok","value":42}

var error = Result.Err<int, string>("failed");
var errorJson = JsonSerializer.Serialize(error);
// Output: {"$type":"err","error":"failed"}

Converting to Option

Option<int> option = result.Ok();  // Some(value) if Ok, None if Err
Option<string> error = result.Err();  // Some(error) if Err, None if Ok

Best Practices

  1. Use descriptive error types instead of just strings

    public enum ParseError { InvalidFormat, OutOfRange, NullInput }
    Result<int, ParseError> Parse(string input) { ... }
    
  2. Prefer Result over exceptions for expected errors

    // Good: Expected errors as Result
    Result<User, NotFoundError> GetUser(int id);
    
    // Exceptions for unexpected errors only
    throw new InvalidOperationException("Database connection lost");
    
  3. Chain operations instead of nested if-statements

    // Instead of multiple if-checks
    var result = GetData()
        .AndThen(Process)
        .AndThen(Validate)
        .Map(Transform);
    
  4. Use Match for exhaustive handling

    return result.Match(
        Ok: value => HandleSuccess(value),
        Err: error => HandleError(error)
    );
    

Performance Considerations

  • Result<T, E> is a value type (struct) with minimal overhead
  • Methods are aggressively inlined where appropriate
  • No heap allocations for the Result itself
  • Suitable for high-performance scenarios

Migration from Exceptions

// Before: Exception-based
public User GetUser(int id)
{
    var user = database.Find(id);
    if (user == null)
        throw new NotFoundException($"User {id} not found");
    return user;
}

// After: Result-based
public Result<User, string> GetUser(int id)
{
    var user = database.Find(id);
    return user != null 
        ? Result.Ok(user)
        : Result.Err($"User {id} not found");
}

License

MIT License - see LICENSE file for details

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.0.1 90 6/20/2025
2.0.0 149 6/19/2025
1.0.1 142 6/18/2025
1.0.0 147 6/18/2025