Table of Contents

Struct Result<TValue>

Namespace
Trellis
Assembly
Trellis.Core.dll

Represents either a successful computation (with a value) or a failure (with an Error).

public readonly struct Result<TValue> : IResult<TValue>, IResult, IEquatable<Result<TValue>>, IFailureFactory<Result<TValue>>

Type Parameters

TValue

Success value type.

Implements
IResult<TValue>
Inherited Members
Extension Methods

Examples

// Creating results
Result<User> success = Result.Ok(user);
Result<User> failure = new Error.NotFound(new ResourceRef("User", "42")) { Detail = "User not found" };

// Pattern matching with Deconstruct
var (isSuccess, value, error) = result;
var message = isSuccess
    ? $"Found user: {value!.Name}"
    : $"Error: {error!.Detail}";

// Or use the safe accessors
if (result.TryGetValue(out var user)) Console.WriteLine(user.Name);
else if (result.Error is { } err) Console.WriteLine(err.Detail);

// Chaining operations
var finalResult = GetUser(id)
    .Bind(user => ValidateUser(user))
    .Map(user => user.Name);

Remarks

Result is the core type for Railway Oriented Programming. It forces explicit handling of both success and failure cases, making error handling visible in the type system. Use Result when an operation can fail in a predictable way that should be handled by the caller.

default(Result<T>) represents a failure carrying a sentinel Error.Unexpected with ReasonCode = "default_initialized". This makes uninitialized state a typed failure rather than a silent success that would hide a programming error. Always construct via Ok<TValue>(TValue) or Fail<TValue>(Error); analyzer TRLS019 flags explicit default(Result<T>) at call sites.

Properties

Error

Gets the error when this result is a failure, or null when it is a success.

public Error? Error { get; }

Property Value

Error

Examples

if (result.Error is { } error)
    return error switch
    {
        Error.NotFound nf => HandleNotFound(nf),
        _ => HandleGeneric(error),
    };

Remarks

Reading this property never throws. The nullable return type is the discriminator: a non-null Error means the result is a failure; null means success. For default(Result<T>), returns the shared Error.Unexpected sentinel so default-initialized failures are observationally equivalent to Result.Fail<T>(new Error.Unexpected("default_initialized")).

IsFailure

True when the result represents failure.

[MemberNotNullWhen(true, "Error")]
public bool IsFailure { get; }

Property Value

bool

True if failed; otherwise false.

Remarks

default(Result<T>).IsFailure is true.

IsSuccess

True when the result represents success.

[MemberNotNullWhen(false, "Error")]
public bool IsSuccess { get; }

Property Value

bool

True if successful; otherwise false.

Methods

AsUnit()

Converts this Result<TValue> to a no-payload Result<TValue>, discarding the success value. Failures preserve their Error.

public Result<Unit> AsUnit()

Returns

Result<Unit>

A Result<TValue> mirroring this result's success/failure state.

Remarks

Use AsUnit() when a pipeline returns a value but the next step only cares about success/failure (e.g., bridging a value-producing operation into a no-payload consumer). This returns the canonical no-payload result shape Result<Unit>. For default-initialized failures the returned result is constructed via Fail(Error) with the shared sentinel — never returns a default-initialized Result<Unit>.

CreateFailure(Error)

Creates a failure result wrapping the given error. Used by generic pipeline behaviors that need to construct failure results without knowing the inner type parameter.

public static Result<TValue> CreateFailure(Error error)

Parameters

error Error

The error describing the failure.

Returns

Result<TValue>

A failed Result<TValue>.

Deconstruct(out bool, out TValue?, out Error?)

Deconstructs the result into its components for pattern matching.

public void Deconstruct(out bool isSuccess, out TValue? value, out Error? error)

Parameters

isSuccess bool

True if the result is successful; otherwise false.

value TValue

The success value if successful; otherwise default.

error Error

The error if failed; otherwise null.

Examples

var (success, value, error) = GetUser(id);
if (success)
    Console.WriteLine($"User: {value!.Name}");
else
    Console.WriteLine($"Error: {error!.Detail}");

Equals(object?)

Determines whether the specified object is equal to the current result.

public override bool Equals(object? obj)

Parameters

obj object

The object to compare with the current result.

Returns

bool

True if the specified object is a Result and is equal to the current result; otherwise false.

Equals(Result<TValue>)

Determines whether the specified result is equal to the current result.

public bool Equals(Result<TValue> other)

Parameters

other Result<TValue>

The result to compare with the current result.

Returns

bool

True if the specified result is equal to the current result; otherwise false.

Remarks

Two results are equal if they have the same success/failure state and equal values/errors. Default-initialized failures use the shared sentinel Error.Unexpected so two default(Result<T>) values are equal, and a default equals an explicit Result.Fail<T>(...) with the same sentinel.

GetHashCode()

Returns a hash code for the current result.

public override int GetHashCode()

Returns

int

A hash code for the current result.

ToString()

Returns a string representation of the result.

public override string ToString()

Returns

string

A string in the format "Success(value)" or "Failure(ErrorCode: detail)".

TryGetError(out Error?)

Attempts to get the error without throwing. Companion to Error for callers that prefer TryParse-style imperative usage where a non-null local binding is desired.

public bool TryGetError(out Error? error)

Parameters

error Error

When this method returns true, contains the error; otherwise null.

Returns

bool

true if the result is a failure; otherwise false.

TryGetValue(out TValue)

Attempts to get the success value without throwing.

[MemberNotNullWhen(false, "Error")]
public bool TryGetValue(out TValue value)

Parameters

value TValue

When this method returns true, contains the success value; otherwise, the default value.

Returns

bool

True if the result is successful; otherwise false.

Remarks

Equivalent to !IsFailure; provided as a TryParse-style convenience that binds the value in a single call.

TryGetValue(out TValue, out Error?)

Attempts to get the success value and the error in a single call, eliminating the need for result.Error! null-suppression after a failed TryGetValue(out TValue).

public bool TryGetValue(out TValue value, out Error? error)

Parameters

value TValue

When this method returns true, contains the success value; otherwise, the default value.

error Error

When this method returns false, contains the error; otherwise null.

Returns

bool

true if the result is successful; otherwise false.

Examples

if (!result.TryGetValue(out var v, out var err))
    return Result.Fail<T>(err); // err is non-null here (flow-analysis verified)
// use v on success

Operators

operator ==(Result<TValue>, Result<TValue>)

Determines whether two results are equal.

public static bool operator ==(Result<TValue> left, Result<TValue> right)

Parameters

left Result<TValue>

The first result to compare.

right Result<TValue>

The second result to compare.

Returns

bool

True if the results are equal; otherwise false.

operator !=(Result<TValue>, Result<TValue>)

Determines whether two results are not equal.

public static bool operator !=(Result<TValue> left, Result<TValue> right)

Parameters

left Result<TValue>

The first result to compare.

right Result<TValue>

The second result to compare.

Returns

bool

True if the results are not equal; otherwise false.