是否存在任何类型的通用字典,试图获取不存在的键将返回null?

时间:2012-10-17 21:22:21

标签: c# .net dictionary

我必须使用.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?

3 个答案:

答案 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是参考类型,则需要进行深层复制,这不值得麻烦。