Either<TLeft, TRight> Struct
Definition
- Namespace
- Bodu.Functional
- Assembly
- Bodu.Core.dll
- Package
- Bodu.Core 1.0.1
- Source
- Either{T,T}.Factories.cs
Represents a disjoint union of two possibilities: either Left(value) carrying a non-null
value of type TLeft, or Right(value) carrying a non-null value of
type TRight.
public readonly struct Either<TLeft, TRight> : IEquatable<Either<TLeft, TRight>>
Type Parameters
TLeftThe type of the value carried on the left side.
TRightThe type of the value carried on the right side.
- Implements
-
IEquatable<Either<TLeft, TRight>>
- Inherited Members
- Extension Methods
Remarks
Either<TLeft, TRight> is a symmetric choice type: neither side is privileged, and no side carries a success or failure connotation - Result<T> owns the railway-oriented bias. Use it when a value is legitimately one of two shapes (for example, a parsed literal that is either a number or a string). Project each side independently with MapLeft<TResult>(Func<TLeft, TResult>) and MapRight<TResult>(Func<TRight, TResult>), exchange the sides with Swap(), and collapse to a single value with Match<TResult>(Func<TLeft, TResult>, Func<TRight, TResult>).
default(Either<TLeft, TRight>) carries neither side. On an uninitialized instance IsLeft
and IsRight are both false, TryGetLeft(out TLeft) and
TryGetRight(out TRight) return false, and every operation that requires a side -
Match, MapLeft, MapRight, and Swap - throws InvalidOperationException.
The type throws on default rather than defaulting to a side because no privileged side exists to default to -
unlike Option<T>, whose default is None, and Result<T>, whose
default is a failure carrying the empty error. Silently treating default as Left(default!)
would fabricate a value the Left(TLeft) factory refuses to accept. This mirrors the
System.Collections.Immutable.ImmutableArray`1.IsDefault precedent for a struct whose uninitialized
state is observable but unusable.
Properties
IsLeft
Gets a value indicating whether this either carries a left value.
public bool IsLeft { get; }
Property Value
- bool
true if the left side is active; otherwise, false - including for
default(Either<TLeft, TRight>), which carries neither side.
Remarks
The type deliberately exposes no throwing value accessor; retrieve the active side's value through TryGetLeft(out TLeft), TryGetRight(out TRight), or Match<TResult>(Func<TLeft, TResult>, Func<TRight, TResult>).
IsRight
Gets a value indicating whether this either carries a right value.
public bool IsRight { get; }
Property Value
- bool
true if the right side is active; otherwise, false - including for
default(Either<TLeft, TRight>), which carries neither side.
Remarks
The type deliberately exposes no throwing value accessor; retrieve the active side's value through TryGetLeft(out TLeft), TryGetRight(out TRight), or Match<TResult>(Func<TLeft, TResult>, Func<TRight, TResult>).
Methods
Equals(Either<TLeft, TRight>)
Determines whether the specified either is equal to the current instance.
public bool Equals(Either<TLeft, TRight> other)
Parameters
otherEither<TLeft, TRight>The either to compare with this instance.
Returns
- bool
true if both instances carry the same side and the active side's values compare equal using Default, or both are uninitialized; otherwise, false.
Remarks
The side participates in equality: Left(x) and Right(x) are never equal, even when
TLeft and TRight are the same type and the values compare equal.
Two uninitialized (default) instances compare equal.
Equals(object?)
Determines whether the specified object is equal to the current either.
public override bool Equals(object? obj)
Parameters
objobjectThe object to compare. Only another Either<TLeft, TRight> can be equal; all other types, including null, return false.
Returns
- bool
true if
objis an Either<TLeft, TRight> equal to this instance; otherwise, false.
GetHashCode()
Returns a hash code for the current instance consistent with Equals(Either<TLeft, TRight>).
public override int GetHashCode()
Returns
- int
A hash code combining the active side with the active side's value, so that
Left(x)andRight(x)hash differently where possible;0for an uninitialized instance.
Left(TLeft)
Creates an either carrying the specified non-null left value.
public static Either<TLeft, TRight> Left(TLeft value)
Parameters
valueTLeftThe left value to wrap. Must not be null.
Returns
- Either<TLeft, TRight>
An Either<TLeft, TRight> whose IsLeft is true.
Examples
var left = Either<int, string>.Left(42); // Left(42)
var right = Either<int, string>.Right("text"); // Right(text)
Remarks
The factory rejects null because a side that is present must carry a usable value; absence is modelled by Option<T>, not by a null side.
Exceptions
- ArgumentNullException
valueis null.
MapLeft<TResult>(Func<TLeft, TResult>)
Projects the left value using the specified selector, passing a right value through untouched.
public Either<TResult, TRight> MapLeft<TResult>(Func<TLeft, TResult> selector)
Parameters
selectorFunc<TLeft, TResult>The projection applied to the left value when the left side is active.
Returns
- Either<TResult, TRight>
Left(selector(value))when the left side is active; otherwise a right-carrying either with the original right value.
Type Parameters
TResultThe left type produced by the selector.
Examples
var doubled = Either<int, string>.Left(21).MapLeft(l => l * 2); // Left(42)
var same = Either<int, string>.Right("text").MapLeft(l => l * 2); // Right(text) - selector not invoked
Remarks
The selector is not invoked when the right side is active. The lift is strict: a null projection result is rejected by the Left(TLeft) factory with ArgumentNullException.
Exceptions
- ArgumentNullException
selectoris null.- InvalidOperationException
The either is
default(Either<TLeft, TRight>)and carries neither side.
MapRight<TResult>(Func<TRight, TResult>)
Projects the right value using the specified selector, passing a left value through untouched.
public Either<TLeft, TResult> MapRight<TResult>(Func<TRight, TResult> selector)
Parameters
selectorFunc<TRight, TResult>The projection applied to the right value when the right side is active.
Returns
- Either<TLeft, TResult>
Right(selector(value))when the right side is active; otherwise a left-carrying either with the original left value.
Type Parameters
TResultThe right type produced by the selector.
Remarks
The selector is not invoked when the left side is active. The lift is strict: a null projection result is rejected by the Right(TRight) factory with ArgumentNullException.
Exceptions
- ArgumentNullException
selectoris null.- InvalidOperationException
The either is
default(Either<TLeft, TRight>)and carries neither side.
Match(Action<TLeft>, Action<TRight>)
Invokes the action for the active side of the either.
public void Match(Action<TLeft> onLeft, Action<TRight> onRight)
Parameters
onLeftAction<TLeft>The action invoked with the left value when the left side is active.
onRightAction<TRight>The action invoked with the right value when the right side is active.
Exceptions
- ArgumentNullException
onLeftoronRightis null.- InvalidOperationException
The either is
default(Either<TLeft, TRight>)and carries neither side.
Match<TResult>(Func<TLeft, TResult>, Func<TRight, TResult>)
Collapses the either to a single value by invoking the branch for the active side.
public TResult Match<TResult>(Func<TLeft, TResult> onLeft, Func<TRight, TResult> onRight)
Parameters
onLeftFunc<TLeft, TResult>The projection invoked with the left value when the left side is active.
onRightFunc<TRight, TResult>The projection invoked with the right value when the right side is active.
Returns
- TResult
The value produced by the invoked branch.
Type Parameters
TResultThe type produced by both branches.
Examples
var label = either.Match(l => $"number {l}", r => $"text {r}");
Exceptions
- ArgumentNullException
onLeftoronRightis null.- InvalidOperationException
The either is
default(Either<TLeft, TRight>)and carries neither side.
Right(TRight)
Creates an either carrying the specified non-null right value.
public static Either<TLeft, TRight> Right(TRight value)
Parameters
valueTRightThe right value to wrap. Must not be null.
Returns
- Either<TLeft, TRight>
An Either<TLeft, TRight> whose IsRight is true.
Remarks
The factory rejects null because a side that is present must carry a usable value; absence is modelled by Option<T>, not by a null side.
Exceptions
- ArgumentNullException
valueis null.
Swap()
Exchanges the sides of the either.
public Either<TRight, TLeft> Swap()
Returns
- Either<TRight, TLeft>
An Either<TLeft, TRight> carrying the same value on the opposite side: a left value becomes the right value and a right value becomes the left value.
Remarks
Swapping twice yields an either equal to the original.
Exceptions
- InvalidOperationException
The either is
default(Either<TLeft, TRight>)and carries neither side.
ToString()
Returns a string representation of the either.
public override string ToString()
Returns
- string
"Left(value)"when the left side is active,"Right(value)"when the right side is active, or"Either()"for an uninitialized instance.
TryGetLeft(out TLeft)
Attempts to retrieve the left value.
public bool TryGetLeft(out TLeft value)
Parameters
valueTLeftWhen this method returns, the left value if the left side is active; otherwise the default value.
Returns
Remarks
Returns false - and never throws - for a right-carrying either and for
default(Either<TLeft, TRight>).
TryGetRight(out TRight)
Attempts to retrieve the right value.
public bool TryGetRight(out TRight value)
Parameters
valueTRightWhen this method returns, the right value if the right side is active; otherwise the default value.
Returns
Remarks
Returns false - and never throws - for a left-carrying either and for
default(Either<TLeft, TRight>).
Operators
operator ==(Either<TLeft, TRight>, Either<TLeft, TRight>)
Determines whether two eithers are equal.
public static bool operator ==(Either<TLeft, TRight> left, Either<TLeft, TRight> right)
Parameters
leftEither<TLeft, TRight>The first either to compare.
rightEither<TLeft, TRight>The second either to compare.
Returns
operator !=(Either<TLeft, TRight>, Either<TLeft, TRight>)
Determines whether two eithers are not equal.
public static bool operator !=(Either<TLeft, TRight> left, Either<TLeft, TRight> right)
Parameters
leftEither<TLeft, TRight>The first either to compare.
rightEither<TLeft, TRight>The second either to compare.
Returns
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |