OptT Structure

Option type which can be either of the two variants: Some(value-of-T) or None.

Definition

Namespace: Orx.Fun.Option
Assembly: Orx.Fun.Option (in Orx.Fun.Option.dll) Version: 1.2.1+ea79806fa5e0e04bfdaef2a1916930e75e2cde74
C#
public readonly struct Opt<T> : IEquatable<Opt<T>>
Inheritance
Object    ValueType    OptT
Implements
IEquatableOptT

Type Parameters

T
Any T.

Constructors

OptT Option type of T: either None or Some value. Parameterless ctor returns None; better use SomeT(T) or NoneT to construct options by adding `using static OptRes.Ext`.

Properties

IsNone Returns whether the option is None or not.
C#
var noneInt = None<int>();
Assert(noneInt.IsNone);

Methods

AndT2(FuncOptT2) Combines two options: this and lazyOther as follows:
  • returns Some of a tuple of both values if both options are Some;
  • returns None otherwise.
lazyOther is computed only if this is Some.
AndT2(OptT2) Combines two options: this and other as follows:
  • returns Some of a tuple of both values if both options are Some;
  • returns None otherwise.
C#
var combined = Some(12).And(Some(true));
Assert.Equal(Some((12, true)), combined);

combined = Some(12).And(None<bool>());
Assert.True(combined.IsNone);

combined = None<int>().And(Some(true));
Assert.True(combined.IsNone);

combined = None<int>().And(None<bool>());
Assert.True(combined.IsNone);
AsNullable Converts the option to nullable of T.
Do Runs action(Unwrap()) only if IsSome; and returns itself back.
C#
// the logging call will only be made if the result of GetOptionalUser is Some of a user.
// Since Do returns back the option, it can still be assigned to var 'user'.
Opt<User> user = GetOptionalUser().Do(u => Log.Info($"User '{u.Name}' grabbed"));
DoIfNone Runs actionOnNone() only if IsNone; and returns itself back. Counterpart of Do(ActionT) for the None variant.
C#
// the logging call will only be made if the result of GetOptionalUser is None.
// Since DoIfNone returns back the option, it can still be assigned to var 'user'.
Opt<User> user = GetOptionalUser().DoIfNone(() => Log.Warning("User could not be read"));
Equals(Object) Returns whether this option is equal to the other.
(Overrides ValueTypeEquals(Object))
Equals(OptT) Returns true if both values are IsNone; or both IsSome and their unwrapped values are equal; false otherwise.
FlatMapTOut(FuncT, OptTOut) Returns None when IsNone; map(val) when IsSome flattening the result. Shorthand combining Map and Flatten calls.
C#
static Opt<User> GetOptionalUser() {
    // method that tries to get the user, which can be omitted.
    ...
}
static Opt<string> GetNickname(User user) {
    // method that tries to get the nickname of the passed-in user; which is optional
    ...
}
Opt<string> nickname = GetOptionalUser().FlatMap(GetNickname);
// equivalent to both below:
nickname = GetOptionalUser().FlatMap(user => GetNickname(user));
nickname = GetOptionalUser().Map(user => GetNickname(user) /*Opt<Opt<string>>*/).Flatten();
FlatMapTOut(FuncT, TaskOptTOut) (async version) Returns None when IsNone; map(val) when IsSome flattening the result. Shorthand combining Map and Flatten calls.
C#
static Opt<User> GetOptionalUser() {
    // method that tries to get the user, which can be omitted.
    ...
}
static Opt<string> GetNickname(User user) {
    // method that tries to get the nickname of the passed-in user; which is optional
    ...
}
Opt<string> nickname = GetOptionalUser().FlatMap(GetNickname);
// equivalent to both below:
nickname = GetOptionalUser().FlatMap(user => GetNickname(user));
nickname = GetOptionalUser().Map(user => GetNickname(user) /*Opt<Opt<string>>*/).Flatten();
GetHashCode Serves as the default hash function.
(Overrides ValueTypeGetHashCode)
GetType
(Inherited from Object)
MapTOut Returns None when IsNone; Some(map(Unwrap())) when IsSome.
C#
// session will be None if the user is None; Some of a session for the user when Some.
Opt<Session> session = GetOptionalUser.Map(user => NewSession(user.Secrets));
MapAsyncTOut (async version) Returns None when IsNone; Some(map(Unwrap())) when IsSome.
C#
// session will be None if the user is None; Some of a session for the user when Some.
Opt<Session> session = GetOptionalUser.Map(user => NewSession(user.Secrets));
MatchTOut(FuncT, TOut, TOut) Maps into whenSome(Unwrap()) whenever IsSome; and into whenNone otherwise.
C#
Opt<User> user = GetOptionalUser(..);
string greeting = user.Match(u => $"Welcome back {u.Name}", "Hello");
greeting = user.Match(whenSome: u => $"Welcome back {u.Name}", whenNone: "Hello");
MatchTOut(FuncT, TOut, FuncTOut) Maps into whenSome(Unwrap()) whenever IsSome; and into lazy whenNone() otherwise. Similar to MatchTOut(FuncT, TOut, TOut) except that None variant is evaluated only when IsNone.
C#
// assuming QueryAnonymousGreeting() is expensive.
Opt<User> user = GetOptionalUser(..);
string greeting = user.Match(u => $"Welcome back {u.Name}", () => QueryAnonymousGreeting());
MatchAsyncTOut (async version) Maps into whenSome(Unwrap()) whenever IsSome; and into lazy whenNone() otherwise. Similar to MatchTOut(FuncT, TOut, TOut) except that None variant is evaluated only when IsNone.
C#
// assuming QueryAnonymousGreeting() is expensive.
Opt<User> user = GetOptionalUser(..);
string greeting = user.Match(u => $"Welcome back {u.Name}", () => QueryAnonymousGreeting());
MatchDo Executes whenSome(Unwrap()) if IsSome; whenNone() otherwise.
C#
static Greet(Opt<User> user) {
    user.MatchDo(
        whenSome: u => Console.WriteLine($"Welcome back {u.Name}"),
        whenNone: Console.WriteLine("Hello")
    );
}
Or(FuncOptT) (lazy version) Combines two options: this and other as follows:
  • returns this if this is Some;
  • returns other otherwise.

In other words, this is a flattened alternative to UnwrapOr(T).

C#
var or = Some(12).Or(Some(13));
Assert.Equal(Some(12), or);

or = Some(12).Or(None<int>());
Assert.Equal(Some(12), or);

or = None<int>().Or(Some(13));
Assert.Equal(Some(13), or);

or = None<int>().Or(None<bool>());
Assert.True(or.IsNone);
Or(OptT) Combines two options: this and other as follows:
  • returns this if this is Some;
  • returns other otherwise.

In other words, this is a flattened alternative to UnwrapOr(T).

C#
var or = Some(12).Or(Some(13));
Assert.Equal(Some(12), or);

or = Some(12).Or(None<int>());
Assert.Equal(Some(12), or);

or = None<int>().Or(Some(13));
Assert.Equal(Some(13), or);

or = None<int>().Or(None<bool>());
Assert.True(or.IsNone);
Pure Simply returns Some<T> function: val => Some(val). Useful for composing functions of Opt<T> type.
SomeIf Returns back None if IsNone. Otherwise, returns Some(value) if validationCriterion(value) holds; None if it does not hold. Especially useful in fluent input validation.
C#
static Opt<Account> MaybeParseAccount(..) { }
static bool IsAccountNumberValid(int number) { }
static bool DoesAccountExist(string code) { }

var account = MaybeParseAccount(..)
                .Validate(acc => IsAccountNumberValid(acc.Number))
                .Validate(acc => DoesAccountExist(acc.Code));
// account will be Some(account) only if:
// - MaybeParseAccount returns Some(account), and further,
// - both IsAccountNumberValid and DoesAccountExist validation checks return true.
ThrowIfNone Returns the option back when IsSome; throws a NullReferenceException when IsNone. Can be called without breaking the flow of chained operations.
C#
var interestRate = GetOptionalUser(input)
    .ThrowIfNone("failed to get the user")
    .Map(user => ComputeInterestRate(user))
    .Unwrap();
ThrowIfNone(String) Returns the option back when IsSome; throws a NullReferenceException when IsNone. Appends the errorMessage to the exception if the message IsSome. Can be called without breaking the flow of chained operations.
C#
var interestRate = GetOptionalUser(input)
    .ThrowIfNone("failed to get the user")
    .Map(user => ComputeInterestRate(user))
    .Unwrap();
ThrowIfNoneE(FuncE) Returns the option back when IsSome; throws a custom exception when IsNone. Exception thrown when IsNone is created by the provided method getException. Can be called without breaking the flow of chained operations.
C#
var interestRate = GetOptionalUser(input)
    .ThrowIfNone(() => new ArithmeticException("sth went wrong"))
    .Map(user => ComputeInterestRate(user))
    .Unwrap();
ToString Returns the text representation of the option.
(Overrides ValueTypeToString)
Unwrap Returns the underlying value when IsSome; or throws when IsNone. Must be called shyly, as it is not necessary to unwrap until the final result is achieved due to Map, FlatMap and TryMap methods.
C#
Opt<int> optAge = "42".ParseIntOrNone();
if (optAge.IsSome) {
    int age = optAge.Unwrap(); // use the uwrapped age
} else { // handle the None case
}
Unwrap(String) Similar to Unwrap method except that the errorMessageIfNone is appended to the error message if IsNone.
UnwrapOr(FuncT) Returns the underlying value when IsSome; or returns lazyFallbackValue() when IsNone. This is a safe way to unwrap the optional, by explicitly handling the None variant. Use the eager UnwrapOr(T) variant if the fallback value is cheap or readily available.
C#
static int GetCapacity(IEnumerable<T> collection, Opt<int> givenCapacity) {
    // capacity will be either the givenCapacity, or the number of elements in the collection.
    // note that, collection.Count() might be expensive requiring linear search.
    // lazy call avoids this call when givenCapacity.IsSome.
    return givenCapacity.UnwrapOr(() => collection.Count());
}
UnwrapOr(T) Returns the underlying value when IsSome; or returns the fallbackValue when IsNone. This is a safe way to unwrap the optional, by explicitly handling the None variant. Use the lazy UnwrapOr(FuncT) variant if the computation of the fallback value is expensive.
C#
Assert(Some(42).UnwrapOr(7) == 42);
Assert(None<int>().UnwrapOr(7) == 7);
UnwrapOrAsync (async version) Returns the underlying value when IsSome; or returns lazyFallbackValue() when IsNone. This is a safe way to unwrap the optional, by explicitly handling the None variant. Use the eager UnwrapOr(T) variant if the fallback value is cheap or readily available.
C#
static int GetCapacity(IEnumerable<T> collection, Opt<int> givenCapacity) {
    // capacity will be either the givenCapacity, or the number of elements in the collection.
    // note that, collection.Count() might be expensive requiring linear search.
    // lazy call avoids this call when givenCapacity.IsSome.
    return givenCapacity.UnwrapOr(() => collection.Count());
}

Operators

Equality(OptT, OptT) Returns true if both values are IsSome and their unwrapped values are equal; false otherwise.
C#
AssertEqual(None<int>() == None<int>(), false);
AssertEqual(None<int>() == Some(42), false);
AssertEqual(Some(42) == None<int>(), false);
AssertEqual(Some(42) == Some(7), false);
AssertEqual(Some(42) == Some(42), true);
Inequality(OptT, OptT) Returns true if either value is IsNone or their unwrapped values are not equal; false otherwise.
C#
AssertEqual(None<int>() != None<int>(), true);
AssertEqual(None<int>() != Some(42), true);
AssertEqual(Some(42) != None<int>(), true);
AssertEqual(Some(42) != Some(7), true);
AssertEqual(Some(42) != Some(42), false);

Fields

IsSome Returns whether the option has Some value or not.
C#
var someInt = Some(12);
Assert(noneInt.IsNone);

See Also