• API Reference

    Show / Hide Table of Contents
    • Recore
      • AbsoluteUri
      • AsyncAction
      • AsyncAction<T>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7, T8, T9>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7, T8>
      • AsyncAction<T1, T2, T3, T4, T5, T6, T7>
      • AsyncAction<T1, T2, T3, T4, T5, T6>
      • AsyncAction<T1, T2, T3, T4, T5>
      • AsyncAction<T1, T2, T3, T4>
      • AsyncAction<T1, T2, T3>
      • AsyncAction<T1, T2>
      • AsyncDefer
      • AsyncFunc<T, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, T8, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, T7, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, T6, TResult>
      • AsyncFunc<T1, T2, T3, T4, T5, TResult>
      • AsyncFunc<T1, T2, T3, T4, TResult>
      • AsyncFunc<T1, T2, T3, TResult>
      • AsyncFunc<T1, T2, TResult>
      • AsyncFunc<TResult>
      • Defer
      • Either
      • Either<TLeft, TRight>
      • Func
      • ObjectExtensions
      • Of<T>
      • OfJsonAttribute
      • Optional
      • Optional<T>
      • RelativeUri
      • Result
      • Result.AsyncCatcher<TValue>
      • Result.Catcher<TValue>
      • Result<TValue, TError>
      • Unit
      • UriExtensions
    • Recore.Collections.Generic
      • AnonymousEqualityComparer<T>
      • ICollectionExtensions
      • IDictionaryExtensions
      • IIterator<T>
      • Iterator
      • LinkedListExtensions
      • ListExtensions
      • MappedComparer<T, TMapped>
      • MappedEqualityComparer<T, TMapped>
    • Recore.Linq
      • Renumerable
    • Recore.Security.Cryptography
      • SecureCompare
    • Recore.Text.Json.Serialization.Converters
      • OverrideEitherConverter<TLeft, TRight>
      • OverrideResultConverter<TValue, TError>
    • Recore.Threading.Tasks
      • TaskExtensions

    Class Either<TLeft, TRight>

    Represents a value that can be one of two types.

    Inheritance
    Object
    Either<TLeft, TRight>
    Implements
    IEquatable<Either<TLeft, TRight>>
    Inherited Members
    Object.Equals(Object, Object)
    Object.GetType()
    Object.MemberwiseClone()
    Object.ReferenceEquals(Object, Object)
    Namespace: Recore
    Assembly: Recore.dll
    Syntax
    [JsonConverter(typeof(EitherConverter))]
    public sealed class Either<TLeft, TRight> : IEquatable<Either<TLeft, TRight>>
    Type Parameters
    Name Description
    TLeft
    TRight
    Remarks

    When working with System.Text.Json, deserializing into Either<TLeft, TRight> can be ambiguous. The default deserialization behavior will try first to deserialize as TLeft, and then as TRight. But, this may return the unintended type if the left deserializer can successfully deserialize the JSON representation of the right.

    A common case is when both TLeft and TRight are POCOs. In that case, Either<TLeft, TRight> will always deserialize as TLeft, filling in default values for any missing properties. For example:

    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    
    class Address
    {
        public string Street { get; set; }
        public string Zip { get; set; }
    }
    
    // Deserializes as a `Person`!
    JsonSerializer.Deserialize<Either<Person, Address>>("{\"Street\":\"123 Main St\",\"Zip\":\"12345\"}")

    You can use OverrideEitherConverter<TLeft, TRight> to specify how to choose between TLeft and TRight based on the properties in the JSON:

    // Look at the JSON to decide which type we have
    options.Converters.Add(new OverrideEitherConverter<Person, Address>(
        deserializeAsLeft: json => json.TryGetProperty("Street", out JsonElement _)));
    
    // Deserializes correctly
    JsonSerializer.Deserialize<Either<Person, Address>>("{\"Street\":\"123 Main St\",\"Zip\":\"12345\"}", options)
    Examples

    Either<TLeft, TRight> creates a type with a value that can be one of two types. In this, it's similar to Optional<T>, which you can think of like Either<T, null> with some extra functionality.

    If you're familiar with TypeScript, you can think of Either<TLeft, TRight> as a union type:

    TLeft | TRight
    

    You create an instance of Either<TLeft, TRight> with one of its constructors, but the implicit conversion operator is pretty convenient too:

    Either<string, int> either = "hello";
    

    Like Optional<T>, the main way to work with Either<TLeft, TRight> is with Switch():

    either.Switch(
        l => Console.WriteLine($"Value is a string: {l}"),
        r => Console.WriteLine($"Value is an int: {r}"));
    

    you can also return a value:

    var message = either.Switch(
        l => $"Value is a string: {l}",
        r => $"Value is an int: {r}");
    

    Compared to Optional<T>, though, where Switch() is more of a last resort when no higher-level idiom is available, Either<TLeft, TRight> leans on Switch() heavily. You can think of Either<TLeft, TRight> as being lower-level than Optional<T>.

    Either<TLeft, TRight> also has OnLeft() and OnRight(), analogous to Optional<T>'s OnValue(). (Note that there's no OnEmpty(); you can just use if (!opt.HasValue) for that.)

    Either<string, bool> newEither = either.OnRight(x => x > 0);
    

    Constructors

    | Improve this Doc View Source

    Either(TLeft)

    Constructs an instance of the type from a value of TLeft.

    Declaration
    public Either(TLeft left)
    Parameters
    Type Name Description
    TLeft left
    | Improve this Doc View Source

    Either(TRight)

    Constructs an instance of the type from a value of TRight.

    Declaration
    public Either(TRight right)
    Parameters
    Type Name Description
    TRight right

    Properties

    | Improve this Doc View Source

    IsLeft

    Indicates whether the value is of type TLeft.

    Declaration
    public bool IsLeft { get; }
    Property Value
    Type Description
    Boolean
    | Improve this Doc View Source

    IsRight

    Indicates whether the value is of type TRight.

    Declaration
    public bool IsRight { get; }
    Property Value
    Type Description
    Boolean

    Methods

    | Improve this Doc View Source

    Equals(Either<TLeft, TRight>)

    Compares two instances of Either<TLeft, TRight> for equality.

    Declaration
    public bool Equals(Either<TLeft, TRight> other)
    Parameters
    Type Name Description
    Either<TLeft, TRight> other
    Returns
    Type Description
    Boolean
    Remarks

    Equality is defined as both objects' underlying values being equal and their underlying values occupying the same position (both left or both right). For example, Either<Color, Day>(Color.Red) != Either<Color, Day>(Day.Monday) even if Color.Red == Day.Monday.

    | Improve this Doc View Source

    Equals(Either<TLeft, TRight>, IEqualityComparer<TLeft>, IEqualityComparer<TRight>)

    Compares two instances of Either<TLeft, TRight> for equality using the given IEqualityComparer<T>.

    Declaration
    public bool Equals(Either<TLeft, TRight> other, IEqualityComparer<TLeft> leftComparer, IEqualityComparer<TRight> rightComparer)
    Parameters
    Type Name Description
    Either<TLeft, TRight> other
    IEqualityComparer<TLeft> leftComparer
    IEqualityComparer<TRight> rightComparer
    Returns
    Type Description
    Boolean
    | Improve this Doc View Source

    Equals(Object)

    Compares this Either<TLeft, TRight> to another object for equality.

    Declaration
    public override bool Equals(object obj)
    Parameters
    Type Name Description
    Object obj
    Returns
    Type Description
    Boolean
    Overrides
    Object.Equals(Object)
    Remarks

    Two Either<TLeft, TRight>s are equal only if they have the same type parameters in the same order. For example, an Either<int, string> and an Either<string, int> will always be nonequal.

    | Improve this Doc View Source

    GetHashCode()

    Returns the hash code of the underlying value.

    Declaration
    public override int GetHashCode()
    Returns
    Type Description
    Int32
    Overrides
    Object.GetHashCode()
    | Improve this Doc View Source

    GetLeft()

    Converts Either<TLeft, TRight> to Optional<TLeft>.

    Declaration
    public Optional<TLeft> GetLeft()
    Returns
    Type Description
    Optional<TLeft>
    | Improve this Doc View Source

    GetRight()

    Converts Either<TLeft, TRight> to Optional<TRight>.

    Declaration
    public Optional<TRight> GetRight()
    Returns
    Type Description
    Optional<TRight>
    | Improve this Doc View Source

    IfLeft(Action<TLeft>)

    Takes an action only if the value is an instance of TLeft.

    Declaration
    public void IfLeft(Action<TLeft> onLeft)
    Parameters
    Type Name Description
    Action<TLeft> onLeft
    | Improve this Doc View Source

    IfRight(Action<TRight>)

    Takes an action only if the value is an instance of TRight.

    Declaration
    public void IfRight(Action<TRight> onRight)
    Parameters
    Type Name Description
    Action<TRight> onRight
    | Improve this Doc View Source

    OnLeft<TResult>(Func<TLeft, TResult>)

    Maps a function over the Either<TLeft, TRight> only if the value is an instance of TLeft.

    Declaration
    public Either<TResult, TRight> OnLeft<TResult>(Func<TLeft, TResult> onLeft)
    Parameters
    Type Name Description
    Func<TLeft, TResult> onLeft
    Returns
    Type Description
    Either<TResult, TRight>
    Type Parameters
    Name Description
    TResult
    | Improve this Doc View Source

    OnRight<TResult>(Func<TRight, TResult>)

    Maps a function over the Either<TLeft, TRight> only if the value is an instance of TRight.

    Declaration
    public Either<TLeft, TResult> OnRight<TResult>(Func<TRight, TResult> onRight)
    Parameters
    Type Name Description
    Func<TRight, TResult> onRight
    Returns
    Type Description
    Either<TLeft, TResult>
    Type Parameters
    Name Description
    TResult
    | Improve this Doc View Source

    Swap()

    Converts this Either<TLeft, TRight> to an Either<TRight, TLeft>.

    Declaration
    public Either<TRight, TLeft> Swap()
    Returns
    Type Description
    Either<TRight, TLeft>
    | Improve this Doc View Source

    Switch(Action<TLeft>, Action<TRight>)

    Takes one of two actions depending on the underlying value.

    Declaration
    public void Switch(Action<TLeft> onLeft, Action<TRight> onRight)
    Parameters
    Type Name Description
    Action<TLeft> onLeft
    Action<TRight> onRight
    | Improve this Doc View Source

    Switch<T>(Func<TLeft, T>, Func<TRight, T>)

    Calls one of two functions depending on the underlying value.

    Declaration
    public T Switch<T>(Func<TLeft, T> onLeft, Func<TRight, T> onRight)
    Parameters
    Type Name Description
    Func<TLeft, T> onLeft
    Func<TRight, T> onRight
    Returns
    Type Description
    T
    Type Parameters
    Name Description
    T
    | Improve this Doc View Source

    ToString()

    Returns the string representation of the underlying value.

    Declaration
    public override string ToString()
    Returns
    Type Description
    String
    Overrides
    Object.ToString()

    Operators

    | Improve this Doc View Source

    Equality(Either<TLeft, TRight>, Either<TLeft, TRight>)

    Determines whether two instances of Either<TLeft, TRight> have the same value.

    Declaration
    public static bool operator ==(Either<TLeft, TRight> lhs, Either<TLeft, TRight> rhs)
    Parameters
    Type Name Description
    Either<TLeft, TRight> lhs
    Either<TLeft, TRight> rhs
    Returns
    Type Description
    Boolean
    | Improve this Doc View Source

    Implicit(TLeft to Either<TLeft, TRight>)

    Converts an instance of a type to an Either<TLeft, TRight>.

    Declaration
    public static implicit operator Either<TLeft, TRight>(TLeft left)
    Parameters
    Type Name Description
    TLeft left
    Returns
    Type Description
    Either<TLeft, TRight>
    | Improve this Doc View Source

    Implicit(TRight to Either<TLeft, TRight>)

    Converts an instance of a type to an Either<TLeft, TRight>.

    Declaration
    public static implicit operator Either<TLeft, TRight>(TRight right)
    Parameters
    Type Name Description
    TRight right
    Returns
    Type Description
    Either<TLeft, TRight>
    | Improve this Doc View Source

    Inequality(Either<TLeft, TRight>, Either<TLeft, TRight>)

    Determines whether two instances of Either<TLeft, TRight> have different values.

    Declaration
    public static bool operator !=(Either<TLeft, TRight> lhs, Either<TLeft, TRight> rhs)
    Parameters
    Type Name Description
    Either<TLeft, TRight> lhs
    Either<TLeft, TRight> rhs
    Returns
    Type Description
    Boolean

    Implements

    System.IEquatable<T>

    Extension Methods

    ObjectExtensions.StaticCast<T>(T)
    ObjectExtensions.Apply<T, TResult>(T, Func<T, TResult>)
    ObjectExtensions.Apply<T>(T, Action<T>)
    • Improve this Doc
    • View Source
    Back to top Generated by DocFX