-
Notifications
You must be signed in to change notification settings - Fork 15
Option_T_
SuccincT.Options.Option<T>
Provides an optional value of type T
. Modelled on F# options. Either contains a T
value, or none
.
Instances of Option<T>
can be created via various means:
- They can be created directly:
var o = new Option<string>(s)
. Ifs
isnull
, then anone
is created, otherwise the option hassome(s)
as its value. - Use the two static methods
Option<T>.None()
andOption<T>.Some(T value)
to create anone
or some value, respectively. In this case, ifOption<T>.Some(null)
is called, anArgumentNullException
is thrown. - A value of
T
can be directly used to create an option, egOption<int> o = 1
createso
as anOption<int>
containing the value,1
andOption<string> o = null
will create anone
.
Option<T>
provides equality via Equals
and the ==
& !=
operator pair. To be equal, both options must have some(value)
and the values must be equal, or both must be none
. Additionally, null
is always equal to none
:
var a = Option<int>.Some(1);
var b = Option<int>.Some(1);
var c = Option<int>.Some(2);
var d = Option<int>.None();
var e = Option<int>.None();
// The following expressions are all true
a == a
a == b
a != c
d == e
a.Equals(b)
d.Equals(e)
For details on using Succinc<T>'s own pattern pattern feature with the Either
type, see Pattern matching on Option<T>
.
As of v8, C# itself has excellent pattern matching support built in to the language. Option<T>
therefore provides the following deconstruct to allow it's use with position pattern matching:
public void Deconstruct(out Option state, out T value);
Option
is an enum with two values, None
and Some
. When state == None
, value
will contain default(T)
. When state == Some
, value
will contain the value stored in the option.
This then allows an option to be pattern matched as follows:
var option = new Option<int>(2);
var result = option is (Some, var i) ? $"Option has int value, {i}" : "Empty";
Note, in order to support pattern matching, the previously supplied deconstruct in Option<T>
had to be removed:
public void Deconstruct(out bool hasValue, out T value)
This introduces a breaking change to any existing deconstruct code.
For a quick fix, the general form var (hasValue, value) = option
can be expressed as:
var (hasValue, value) = option is (Some, var v) ? (true, v) : (false, default);
but it's not pretty. So you'll very likely want to refactor the code to accommodate this change at some stage.
As an alternative to using an option in a functional style, its value can be directly accessed by more traditional, imperative style C# code. Three read-only properties are provided for this purpose:
public bool HasValue { get; }
True if the option has a value; else false.
public T Value { get; }
If HasValue
is true, this will return the value held by the option. Otherwise an InvalidOperationException
will be thrown.
public T ValueOrDefault { get; }
If HasValue
is true, this will return the value held by the option. Otherwise it will return default(T)
Option<T>
provides a number of extension methods for manipulating the value, if present.
public static IEnumerable<T> Choose<T>(this IEnumerable<Option<T>> options)
Returns a new enumeration of options containing just those with a value. Equivalent to executing:
from option in options where option.HasValue select option;
public static Option<T> Flatten<T>(this Option<Option<T>> option)
"Flatterns" (or de-nests) an option of option of T
.
For an Option<Option<T>>
with none
, an Option<T>
with none
is returned.
For an Option<Option<T>>
with a value, an Option<T>
with that same value is returned.
public static Option<TOutput> Map<TInput, TOutput>(this Option<TInput> input,
Func<TInput, TOutput> f)
Maps the input option to an output option, via the supplied function.
For an Option<TInput>
with none
, an Option<TOutput>
with none
is returned.
For an Option<TInput>
with a value, an Option<TOutput>
with the result of applying f(input.Value)
to that value, is returned.
public static Option<T> Or<T>(this Option<T> option, Option<T> anotherOption)
Returns option
if it has a value, otherwise anotherOption
is returned.
public static Option<T> Or<T>(this Option<T> option,
Func<Option<T>> lazyAnotherOption)
Returns option
if it has a value, otherwise lazyAnotherOption()
is called, and the result of that function is returned.
public static Option<T> Some<T>(this T value)
Returns an Option<T>
with Value
set to the value of the item converted. This allows the easy creation of an option from a value, using var
:
var option = "a string".Some();
// option is Option<string> and option.Value == "a string"
Finally, a number of extension methods for IEnumerable<T>
, IDictionary<T>
and for handling casting and null
in general types are provided. See Extension methods for existing types, which use Option<T>
for details.
Action
/Func
conversionsCycle
methods- Converting between
Action
andFunc
- Extension methods for existing types that use
Option<T>
- Indexed enumerations
IEnumerable<T>
cons- Option-based parsers
- Partial function applications
- Pattern matching
- Pipe Operators
- Typed lambdas
Any
Either<TLeft,TRight>
None
Option<T>
Success<T>
Union<T1,T2>
Union<T1,T2,T3>
Union<T1,T2,T3,T4>
Unit
ValueOrError