In F#, the option type is a built-in Discriminated Union type which allows to handle nicely the fact that an expression can represent some value or none. In C#, we have almost this construct when we use the Nullable<T>, but as I’ve already stated before, this type is available only for value types. Here is an option type that deals also with reference types.
I’ve already played with an Irreleventable<T> type in the past, and the implementation of it is quite the same as what I’ll do today, but the semantics are different, and I don’t want to re-use this type in a misleading way.
So today, I bring you “yet another option type” in C# :
public struct Option<T> { private readonly bool isSome; public bool IsSome { get { return isSome; } } private readonly T value; public T Value { get { if (!isSome) throw new NotSupportedException(); return value; } } private Option(bool isSome, T value) { this.isSome = isSome; this.value = value; } public static Option<T> Some(T value) { return new Option<T>(true, value); } public static Option<T> None() { return new Option<T>(false, default(T)); } public override int GetHashCode() { return isSome ? value.GetHashCode() : -1; } public override bool Equals(object other) { if (!(other is Option<T>)) return false; Option<T> otherOption = (Option<T>)other; return IsSome ? (value == null && otherOption.Value == null) || value.Equals(otherOption.Value) : !otherOption.IsSome; } public override string ToString() { return this.IsSome ? this.value.ToString() : String.Empty; } }
The only noticeable differences with the Irreleventable type are the (chosen) lack of conversion operators, and the equality comparison, as an Option<T> will never be considered equal to an instance of T (unlike the Irreleventable).
Why would I write a blog post simply to introduce this type, without any context ? More to come soon.