哪种机制是扩展Dictionary以处理丢失键的更好方法,为什么?

我发现自己有很多小麻烦 – 我有一个Dictionary ,其中包含可能存在或不存在的值。

所以正常的行为是使用索引器,如下所示:

 object result = myDictionary["key"]; 

但是,如果"key"不在字典中,则抛出KeyNotFoundException ,所以你这样做:

 object val; if (!myDictionary.TryGetValue("key", out val)) { val = ifNotFound; } 

这很好,除了我可以连续加载这些 – TryGetValue开始觉得可怕的笨重。

因此选项1是一种扩展方法:

 public static TValue TryGet( this Dictionary input, TKey key, TValue ifNotFound = default(TValue)) { TValue val; if (input.TryGetValue(key, out val)) { return val; } return ifNotFound; } 

这让我做:

 object result = myDictionary.TryGet("key1") ?? ifNotFound; int i = anotherDictionary.TryGet("key2", -1); 

这很简单,但使用类似于现有实例方法的名称的附加扩展方法可能会增加混淆并降低可维护性。 它也与字典的索引器集不一致 – 它将处理丢失的密钥。

所以选项2是IDictionary的新实现, IDictionary来自Dictionary的隐式转换Dictionary但是返回default(TValue)而不是抛出KeyNotFoundException的索引器。

那让我做:

 ForgivingDictionary dict = myDictionary; object val = dict["key"] ?? ifNotFound; // do stuff to val, then... dict["key"] = val; 

所以现在get和set值是一致的,但是值类型更加混乱, ForgivingDictionary涉及更多代码。

这两种方法看起来都很“混乱” – 在.Net中有更好的方法吗?

这两种方法都会产生可能导致混淆的妥协,但是比另一种方法更明显/更明确吗? 为什么?

在命名一个旨在替换现有方法的扩展方法时,我倾向于在方法名称中添加特异性而不是缩短它:

 GetValueOrDefault(...) 

对于ForgivingDictionary ,您可以约束TKey ,使其不能是值类型。 但是,如果必须处理其中的值类型,则将返回值类型的内容,最佳选择是返回default(TKey)因为您不能返回null

老实说,我会使用扩展方法。

编辑GetValueOrDefault() ,当然,如果找不到密钥,就不会添加到字典中。 如果没有找到,我会返回一个默认值,因为它是如何命名的。 如果有人想要插入它,一个好名字就是GetValueOrInsertDefault()

我无法从您的问题中推断出未找到密钥时应该怎么做。 我可以想象在这种情况下不应该做什么,但我也可以想象相反的情况。 无论如何,对于您描述的一系列这些TryGetValue语句,优雅的替代方法是使用以下扩展方法之一。 我提供了两个选项,具体取决于当字典不包含密钥时是否应该执行某些操作:

 ///  Iterates over all values corresponding to the specified keys, ///for which the key is found in the dictionary.  public static IEnumerable TryGetValues(this Dictionary dictionary, IEnumerable keys) { TValue value; foreach (TKey key in keys) if (dictionary.TryGetValue(key, out value)) yield return value; } ///  Iterates over all values corresponding to the specified keys, ///for which the key is found in the dictionary. A function can be specified to handle not finding a key.  public static IEnumerable TryGetValues(this Dictionary dictionary, IEnumerable keys, Action notFoundHandler) { TValue value; foreach (TKey key in keys) if (dictionary.TryGetValue(key, out value)) yield return value; else notFoundHandler(key); } 

有关如何使用它的示例代码是:

 TKey[] keys = new TKey{...}; foreach(TValue value in dictionary.TryGetValues(keys)) { //some action on all values here } 

也许

 public static TValue TryGet(this Dictionary input, TKey key) { return input.ContainsKey(key) ? input[key] : *some default value*; }