Skip to content

Result Type

Zeid Youssefzadeh edited this page Feb 17, 2025 · 3 revisions

Overview

This library provides robust result types for implementing railway-oriented programming (ROP) patterns in C#. The Result<TValue> struct and Result static class enable explicit, exception-free error handling while adhering to functional programming principles.

Key Features:

  1. Immutability & Thread Safety: Instances cannot be modified after creation, ensuring predictable behavior in concurrent scenarios.
  2. Null Safety: Success values are guaranteed non-null through guard clauses during initialization.
  3. Value Semantics: Lightweight record struct design minimizes heap allocations and supports equality comparisons.
  4. Explicit State Handling: Clear IsSuccess/IsFailure indicators and pattern matching eliminate ambiguous state checks.
  5. Error Conversion: Automatic wrapping of exceptions into ResultError for consistent error handling.
  6. Seamless Interop: Implicit conversions from values (TValue), errors (ResultError), and exceptions.
  7. Extension Methods: Simplified workflows with methods like Map, Bind, and Match.

Public API Reference

The Result<TValue>.Value and Result<TValue>.Error properties are only available through extension methods as public access to those properties violates the Railway-oriented programming (ROP) principles and the purpose of this library. The Result<TValue> struct provides the following public properties:

Property Type Description
IsSuccess bool Indicates if the operation succeeded (true = success)
IsFailure bool Indicates if the operation failed (true = failure)
IsDefault bool True if success value is default forTValue (e.g., 0 for int)

^ Back To Top

Usage

Following examples are based on the Result static class and Result<TValue> record struct basic use cases. There are extensive extension methods available for Result<TValue> is explained in other pages.

Examples: Basic Success/Failure creation

// Successful result
// Throws `ArgumentNullException` if value is null
Result<int> successResult = Result.Success(42);
Console.WriteLine(successResult.IsSuccess); // true

// Failure result
Result<int> failureResult = Result.Failure<int>("Operation failed");
Console.WriteLine(failureResult.IsFailure); // true

// Failure result from exception
Result<int> exResult = Result.FromException<int>(new Exception("Error"));
Console.WriteLine(exResult.IsFailure); // true

Examples: Implicit Operators

// From value
// Throws `ArgumentNullException` if value is null
Result<int> result = 42; 

// From error
Result<int> result = ResultError.New("Error");

// From exception
Result<int> result = new InvalidOperationException();

Examples: Error Handling

public Result<int> Divide(int numerator, int denominator)
{
    if (denominator == 0)
        return Result.Failure<int>("Division by zero");
  // implicit conversion to Result<int>
  // Throws `ArgumentNullException` if value is null
    return numerator / denominator;
}

var result = Divide(10, 0);

Console.WriteLine(result.IsFailure); // true
result.Match(
    success: value => Console.WriteLine($"Got value: {value}"), // Skiped
    failure: error => Console.WriteLine($"Error: {error.Message}") // Executed
     ); // Prints: "Error: Division by zero"

^ Back To Top

Clone this wiki locally