Struct OneOf<T1, T2>

Namespace
REslava.Result.AdvancedPatterns
Assembly
REslava.Result.dll

Represents a value that can be one of two possible types. A type-safe discriminated union for functional programming patterns.

public readonly struct OneOf<T1, T2> : IEquatable<OneOf<T1, T2>>

Type Parameters

T1

The first possible type.

T2

The second possible type.

Implements
IEquatable<OneOf<T1, T2>>
Inherited Members
Extension Methods

Remarks

OneOf<T1, T2> provides a type-safe way to represent a value that can be one of two types. This is useful for scenarios where you need to handle different types of values or errors without using null references or exceptions.

Common use cases include: - Error handling with typed errors: OneOf<Error, Success> - Configuration values: OneOf<string, int> - API responses: OneOf<ValidationError, Data>

// Error handling
OneOf<Error, User> user = GetUser(id);
return user.Match(
    error => HandleError(error),
    user => ProcessUser(user)
);

// Configuration parsing OneOf<string, int> config = GetConfig("timeout"); int timeout = config.Match( str => int.Parse(str), num => num );

Properties

AsT1

Gets the value as T1 if it contains T1, otherwise throws InvalidOperationException.

public T1 AsT1 { get; }

Property Value

T1

Exceptions

InvalidOperationException

Thrown when the OneOf contains T2.

AsT2

Gets the value as T2 if it contains T2, otherwise throws InvalidOperationException.

public T2 AsT2 { get; }

Property Value

T2

Exceptions

InvalidOperationException

Thrown when the OneOf contains T1.

IsT1

Gets whether the OneOf contains a value of type T1.

public bool IsT1 { get; }

Property Value

bool

IsT2

Gets whether the OneOf contains a value of type T2.

public bool IsT2 { get; }

Property Value

bool

Methods

Bind<TNewT2>(Func<T2, OneOf<T1, TNewT2>>)

Binds the T2 value if present, otherwise propagates T1.

public OneOf<T1, TNewT2> Bind<TNewT2>(Func<T2, OneOf<T1, TNewT2>> binder)

Parameters

binder Func<T2, OneOf<T1, TNewT2>>

The function that takes T2 and returns a OneOf.

Returns

OneOf<T1, TNewT2>

The result of the binder function or the original T1.

Type Parameters

TNewT2

The new T2 type.

Examples

OneOf<Error, int> userId = GetUserId();
OneOf<Error, User> user = userId.Bind(id => GetUser(id));

Remarks

Bind (also known as flatMap or chain) allows you to chain operations that return OneOf. This is useful for sequential operations where each step might return a different type.

Exceptions

ArgumentNullException

Thrown when binder is null.

Equals(OneOf<T1, T2>)

Determines equality between two OneOf instances.

public bool Equals(OneOf<T1, T2> other)

Parameters

other OneOf<T1, T2>

The other OneOf to compare with.

Returns

bool

true if the OneOf instances are equal; otherwise, false.

Equals(object?)

Determines equality between the OneOf and another object.

public override bool Equals(object? obj)

Parameters

obj object

The object to compare with.

Returns

bool

true if the objects are equal; otherwise, false.

Filter(Func<T2, bool>, T1)

Filters the T2 value if it satisfies the predicate, otherwise converts to T1.

public OneOf<T1, T2> Filter(Func<T2, bool> predicate, T1 fallbackT1)

Parameters

predicate Func<T2, bool>

The condition to test the T2 value against.

fallbackT1 T1

The T1 value to use when the predicate fails.

Returns

OneOf<T1, T2>

The original OneOf if the predicate is true, otherwise the fallback T1.

Examples

OneOf<Error, User> user = GetUser(id);
OneOf<Error, User> activeUser = user.Filter(u => u.IsActive, new UserInactiveError());

Remarks

Filter allows you to conditionally keep or discard the T2 value. If the OneOf contains T1, the predicate is not evaluated and T1 is returned.

Exceptions

ArgumentNullException

Thrown when predicate is null.

FromT1(T1)

Creates a OneOf containing a T1 value.

public static OneOf<T1, T2> FromT1(T1 value)

Parameters

value T1

The T1 value to wrap.

Returns

OneOf<T1, T2>

A OneOf containing the specified T1 value.

Examples

OneOf<Error, User> result = OneOf<Error, User>.FromT1(new NotFoundError());

FromT2(T2)

Creates a OneOf containing a T2 value.

public static OneOf<T1, T2> FromT2(T2 value)

Parameters

value T2

The T2 value to wrap.

Returns

OneOf<T1, T2>

A OneOf containing the specified T2 value.

Examples

OneOf<Error, User> result = OneOf<Error, User>.FromT2(new User("Alice"));

GetHashCode()

Returns the hash code for the OneOf.

public override int GetHashCode()

Returns

int

The hash code.

Map<TNewT2>(Func<T2, TNewT2>)

Maps the T2 value if present, otherwise propagates T1.

public OneOf<T1, TNewT2> Map<TNewT2>(Func<T2, TNewT2> mapper)

Parameters

mapper Func<T2, TNewT2>

The function to apply to the T2 value.

Returns

OneOf<T1, TNewT2>

A new OneOf with the mapped T2 value or the original T1.

Type Parameters

TNewT2

The new T2 type.

Examples

OneOf<Error, User> user = GetUser(id);
OneOf<Error, string> userName = user.Map(u => u.Name);

Remarks

Map allows you to transform the T2 value without unwrapping the OneOf. If the OneOf contains T1, the mapper function is not called and T1 is propagated.

Exceptions

ArgumentNullException

Thrown when mapper is null.

Match<TResult>(Func<T1, TResult>, Func<T2, TResult>)

Pattern matching - executes the appropriate function based on the contained type.

public TResult Match<TResult>(Func<T1, TResult> case1, Func<T2, TResult> case2)

Parameters

case1 Func<T1, TResult>

The function to execute when the OneOf contains T1.

case2 Func<T2, TResult>

The function to execute when the OneOf contains T2.

Returns

TResult

The result of the executed function.

Type Parameters

TResult

The type of the result.

Examples

OneOf<Error, User> result = GetUser(id);
string message = result.Match(
    error => $"Error: {error.Message}",
    user => $"User: {user.Name}"
);

Remarks

Match provides a type-safe way to handle both possible cases without casting. This is similar to pattern matching in functional languages.

Exceptions

ArgumentNullException

Thrown when case1 or case2 is null.

Switch(Action<T1>, Action<T2>)

Executes an action based on the contained type.

public void Switch(Action<T1> case1, Action<T2> case2)

Parameters

case1 Action<T1>

The action to execute when the OneOf contains T1.

case2 Action<T2>

The action to execute when the OneOf contains T2.

Examples

OneOf<Error, User> result = GetUser(id);
result.Switch(
    error => Console.WriteLine($"Error: {error.Message}"),
    user => Console.WriteLine($"User: {user.Name}")
);

Remarks

Switch is useful for side effects when you don't need to return a value.

Exceptions

ArgumentNullException

Thrown when case1 or case2 is null.

ToString()

Converts to string for debugging.

public override string ToString()

Returns

string

A string representation of the OneOf.

Examples

OneOf<Error, User> user = new User("Alice");
Console.WriteLine(user.ToString()); // "OneOf<T1, T2>(T2: User { Name = Alice })"

Remarks

Returns the string representation of the contained value with type information. This is primarily useful for debugging and logging.

Operators

operator ==(OneOf<T1, T2>, OneOf<T1, T2>)

Equality operator for OneOf instances.

public static bool operator ==(OneOf<T1, T2> left, OneOf<T1, T2> right)

Parameters

left OneOf<T1, T2>

The left OneOf.

right OneOf<T1, T2>

The right OneOf.

Returns

bool

true if the OneOf instances are equal; otherwise, false.

implicit operator OneOf<T1, T2>(T1)

Implicit conversion from T1 to OneOf<T1, T2>.

public static implicit operator OneOf<T1, T2>(T1 value)

Parameters

value T1

The T1 value to convert.

Returns

OneOf<T1, T2>

A OneOf containing the T1 value.

Examples

OneOf<Error, User> result = new NotFoundError(); // Implicit conversion

implicit operator OneOf<T1, T2>(T2)

Implicit conversion from T2 to OneOf<T1, T2>.

public static implicit operator OneOf<T1, T2>(T2 value)

Parameters

value T2

The T2 value to convert.

Returns

OneOf<T1, T2>

A OneOf containing the T2 value.

Examples

OneOf<Error, User> result = new User("Alice"); // Implicit conversion

operator !=(OneOf<T1, T2>, OneOf<T1, T2>)

Inequality operator for OneOf instances.

public static bool operator !=(OneOf<T1, T2> left, OneOf<T1, T2> right)

Parameters

left OneOf<T1, T2>

The left OneOf.

right OneOf<T1, T2>

The right OneOf.

Returns

bool

true if the OneOf instances are not equal; otherwise, false.