我必须使用.ContainsKey
而不是仅仅在字典中执行value==null
,这让我感到很恼火。现实生活中的例子:
var dictionary = new Dictionary<string, FooBar>();
var key = "doesnt exist";
var tmp = dictionary[key] ?? new FooBar(x, y);
相反,我有这些选择:
var key = "doesnt exist";
FooBar tmp = null;
if (dictionary.ContainsKey(key))
{
tmp = dictionary[key];
} else {
tmp = new FooBar(x, y);
}
或者这个:
FooBar tmp = null;
if (!Dictionary.TryGetValue(key, out tmp))
{
tmp = new FooBar(x, y);
}
对我来说,这段代码非常详细。是否有一个内置的泛型类实现IDictionary(或以其他方式允许键值类型访问)但在我尝试查找键时不会抛出异常,而是返回null?
答案 0 :(得分:8)
问题是Dictionary<TKey, TValue>
允许您存储 null
作为值,因此您不知道密钥是否不存在,或者只是值null
。另一个问题是null
仅对作为引用类型(或TValue
)的Nullable<T>
类型有效。
现在,说,您可以自己编写扩展方法:
public static class DictionaryUtilities
{
public static TValue SafeGet<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue defaultIfNotFound = default(TValue))
{
TValue value;
return dict.TryGetValue(key, out value) ? value : defaultIfNotFound;
}
}
通过这种方式,您可以像这样查询字典:
var sample = new Dictionary<int, string> { {1, "One"}, {2, "Two}, {3, "Three"} };
var willBeNull = sample.SafeGet(4);
var willBeHi = sample.SafeGet(4, "HI!");
当然,如果TValue
是值类型(即,如果值类型为int
,则上面的代码将返回值类型的默认值,它将返回{{1}默认情况下,未找到。)
但是,您可以再次创建两个表单,一个表示0
约束为TValue
,另一个表示class
,表示您可以返回值struct
类型...
答案 1 :(得分:2)
对于泛型集合null
并不总是有效值,您不能编写返回null
的泛型方法。它必须是默认值(T)。
如果您确定不会将其用作值
,则可以轻松创建一个返回默认值(T)的实用程序方法答案 2 :(得分:0)
如果您延长,则必须每次都传递默认值 那可能就是你想要的 可以实现Dictionary并在ctor中传递一个默认值。
public class DictionaryWithDefault<T1,T2> : Dictionary<T1,T2>
{
private T2 t2Default;
public new T2 this[T1 t1]
{ // indexer - if the key is not present return the default
get
{
T2 t2t;
return TryGetValue(t1, out t2t) ? t2t : t2Default;
}
set {
base[t1] = value;
}
}
public DictionaryWithDefault(T2 _t2) { this.t2Default = _t2; }
}
如果希望Dictionary不允许值为null,则覆盖Add。
借用JamesMH +1的一些语法
我使用的东西是带有复合键的字典。
如果你改变了默认值,那么它会改变t2Default值
我正在努力。
如果T2是值类型,那么这是有效的
如果T2是参考类型,则需要进行深层复制,这不值得麻烦。