.NET Dictionary:获取或创建新的
我经常发现自己创建了一个带有非平凡值类(例如List
)的Dictionary
,然后在填写数据时总是编写相同的代码模式。
例如:
var dict = new Dictionary<string, List>(); string key = "foo"; string aValueForKey = "bar";
也就是说,我想在与"foo"
键对应的列表中插入"bar"
,其中键"foo"
可能不会映射到任何内容。
这是我使用不断重复的模式的地方:
List keyValues; if (!dict.TryGetValue(key, out keyValues)) dict.Add(key, keyValues = new List()); keyValues.Add(aValueForKey);
这样做有更优雅的方式吗?
相关问题没有这个问题的答案:
- 是否有一个IDictionary实现,在缺少键而不是抛出时返回null?
- 在c#字典中只查找或插入一个查找
- 如果密钥不存在,则字典返回默认值
我们对此略有不同,但效果类似:
public static TValue GetOrCreate(this IDictionary dict, TKey key) where TValue : new() { TValue val; if (!dict.TryGetValue(key, out val)) { val = new TValue(); dict.Add(key, val); } return val; }
所谓的:
var dictionary = new Dictionary>(); List numbers = dictionary.GetOrCreate("key");
它利用了公共无参数构造函数的generics约束: where TValue : new()
。
为了帮助发现,除非扩展方法非常特定于狭窄的问题,否则我们倾向于将扩展方法放在它们扩展的类型的命名空间中,在这种情况下:
namespace System.Collections.Generic
大多数情况下,使用该类型的人在顶部定义了using
语句,因此IntelliSense也会在代码中找到它的扩展方法。
与许多编程问题一样,当你发现自己做了很多事情时,将它重构为一个方法:
public static void MyAdd( this Dictionary dictionary, TKey key, TValue value) where TCollection : ICollection, new() { TCollection collection; if (!dictionary.TryGetValue(key, out collection)) { collection = new TCollection(); dictionary.Add(key, collection); } collection.Add(value); }
好的,不同的方法:
public static bool TryAddValue(this System.Collections.Generic.IDictionary> dictionary, TKey key, TValue value) { // Null check (useful or not, depending on your null checking approach) if (value == null) return false; List tempValue = default(List ); try { if (!dictionary.TryGetValue(key, out tempValue)) { dictionary.Add(key, tempValue = new List ()); } else { // Double null check (useful or not, depending on your null checking approach) if (tempValue == null) { dictionary[key] = (tempValue = new List ()); } } tempValue.Add(value); return true; } catch { return false; } }
通过这种方式,您必须“尝试将”值添加到通用List(显然可归于generics集合),null检查并尝试获取Dictionary中的现有键/值。 用法和示例:
var x = new Dictionary>(); x.TryAddValue("test", null); // return false due to null value. Doesn't add the key x.TryAddValue("test", "ok"); // it works adding the key/value x.TryAddValue("test", "ok again"); // it works adding the value to the existing list
希望能帮助到你。
那怎么样?
var keyValues = dictionary[key] = dictionary.ContainsKey(key) ? dictionary[key] : new List(); keyValues.Add(aValueForKey);