使用Option<T>类型二不是null是解决空值问题的另一种策略。与null相比,Option<T>类型是一个更安全的方法,因为它同样适用于值类型和引用类型。而且它的功能更强大,因为它用“元数据”的方法保存一个值的额外信息,因此允许我们使用某个类型的整个值域,包括null本身。以下是完整代码。
public sealed class Option
{
private Option() { }
public static Option<T> Some<T>(T value)
{
return new Option<T>(value);
}
public static readonly Option None = new Option();
}
public static class OptionHelpers
{
public static Option<T> ToOption<T>(this T val)
{
return Option.Some(val);
}
public static Option<T> ToNotNullOption<T>(this T val) where T : class
{
return val != null ? val.ToOption() : Option.None;
}
}
public sealed class Option<T>
{
private readonly T value;
public T Value
{
get { return value; }
}
private readonly bool hasValue;
public bool HasValue
{
get { return hasValue; }
}
public bool IsSome
{
get { return hasValue; }
}
public bool IsNone
{
get { return !hasValue; }
}
public Option(T value)
{
this.value = value;
this.hasValue = true;
}
private Option()
{
}
private static readonly Option<T> None = new Option<T>();
public static bool operator ==(Option<T> a, Option<T> b)
{
return a.HasValue == b.HasValue &&
EqualityComparer<T>.Default.Equals(a.Value, b.Value);
}
public static bool operator !=(Option<T> a, Option<T> b)
{
return !(a == b);
}
public static implicit operator Option<T>(Option option)
{
return None;
}
public override int GetHashCode()
{
int hashCode = hasValue.GetHashCode();
if (hasValue)
hashCode ^= value.GetHashCode();
return hashCode;
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public Option<R> Bind<R>(Func<T, Option<R>> g)
{
if (IsNone)
return Option.None;
return g(Value);
}
}