避免空引用

C#開發人員得到了很多空引用異常來處理。F#開發人員沒有,因為他們有 Option 型別。Option <>型別(有些人更喜歡 Maybe <>作為名稱)提供 Some 和 None 返回型別。它明確表示方法可能即將返回空記錄。

例如,你無法閱讀以下內容並知道是否必須處理空值。

var user = _repository.GetUser(id);

如果你確實知道可能的 null,你可以引入一些樣板程式碼來處理它。

var username = user != null ? user.Name : string.Empty;

如果我們返回了選項<>,該怎麼辦?

Option<User> maybeUser = _repository.GetUser(id);

程式碼現在明確表示我們可能返回了 None 記錄,並且需要檢查 Some 或 None 的樣板程式碼:

var username = maybeUser.HasValue ? maybeUser.Value.Name : string.Empty;

以下方法顯示如何返回 Option <>

public Option<User> GetUser(int id)
{
    var users = new List<User>
    {
        new User { Id = 1, Name = "Joe Bloggs" },
        new User { Id = 2, Name = "John Smith" }
    };

    var user = users.FirstOrDefault(user => user.Id == id);

    return user != null ? new Option<User>(user) : new Option<User>();
}

這是 Option <>的最小實現。

public struct Option<T>
{
    private readonly T _value;

    public T Value
    {
        get
        {
            if (!HasValue)
                throw new InvalidOperationException();

            return _value;
        }
    }

    public bool HasValue
    {
        get { return _value != null; }
    }

    public Option(T value)
    {
        _value = value;
    }

    public static implicit operator Option<T>(T value)
    {
        return new Option<T>(value);
    }
}

為了演示上述,可以使用 C#REPL 執行 avoidNull.csx

如上所述,這是一個最小的實現。搜尋 MaybeNuGet 包將會出現一些好的庫。