4

我必须使用而不是仅仅在字典中.ContainsKey做 a真的让我很恼火。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?

4

3 回答 3

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,默认情况下它将返回0未找到。)

不过,您可以再次创建两种形式,一种TValue是受限的class,另一种struct是允许您返回Nullable<T>值类型的...

于 2012-10-17T21:26:54.207 回答
2

对于泛型集合null并不总是有效值,您不能编写返回的泛型方法null。它必须是默认值(T)。

如果您确定不会将其用作值,则可以轻松创建返回 default(T) 的实用程序方法

于 2012-10-17T21:30:55.817 回答
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 是引用类型,则需要进行深层复制,这不值得麻烦。

于 2012-10-17T22:34:31.520 回答