我不喜歡對付null
所以我的實現看起來就像這樣:
interface Maybe<T> {
bool HasValue {get;}
T Value {get;}
}
class Nothing<T> : Maybe<T> {
public bool HasValue { get { return false; } }
public T Value { get { throw new Exception(); } }
public static const Nothing<T> Instance = new Nothing<T>();
}
class Just<T> : Maybe<T> {
private T _value;
public bool HasValue { get { return true; } }
public T Value { get { return _value; } }
public Just(T val) {
_value = val;
}
}
Maybe
是可以包含值或不是對象。請注意,Nothing
類包含靜態字段Instance
。每次我們需要從函數返回Nothing
時,我們可以使用此值而不是創建新值。
現在,我們需要建立我們自己的字典類:
class MyDictionary<TKey, TValue>
{
private Dictionary<TKey, TValue> _dict;
...
public Maybe<TValue> this[TKey key] {
TValue val;
if (_dict.TryGetValue(key, out val)) {
return new Just<TValue>(val);
return Nothing<TValue>.Instance;
}
}
這種方法的優點是不明確的,因爲C#沒有模式匹配。但是,它可以與dynamic
進行仿真:
void ProcessResult(Just<string> val) {
Console.WriteLine(val);
}
void ProcessResult(Nothing<string> n) {
Console.WriteLine("Key not found");
}
var dict = new MyDictionary<string, string>();
...
dynamic x = dict["key"];
ProcessResult(x);
我認爲這是表達事實,詞典總是無法返回有意義的結果非常明確的方式。另外,對於讀者來說明顯的是,函數重載ProcessResult(Just<T>)
將僅針對字典中存在的值而被調用,並且在未找到密鑰的情況下將調用其他重載。
優點:
缺點:
如果你不願意改變你的字典,如康斯坦丁的答案中提到的那樣,實現空返回的簡單擴展方法也可以。 – ryadavilli
注意:值類型沒有'null'的好概念...所以要注意'字典'並試圖返回類型爲'int'的特殊不存在的值:) –
@AlexeiLevenkov好點。當我解決了這個問題時,我不需要使用值類型爲 – horgh