5

如果我使用 a Hashtable,我可以编写如下代码:

object item = hashtable[key] ?? default_value;

无论是否key出现在Hashtable.

我不能用Dictionary<TKey. TValue>. 如果字典中不存在该键,则会抛出一个KeyNotFoundException. 所以我必须写这样的代码:

MyClass item;
if (!(dict.TryGetValue(key, out item))
{
   item = default_value;
}

我想知道这是为什么。 Dictionary<TKey, TValue>只是一个包装Hashtable。为什么要加上这个限制?

编辑:

从另一个角度来看 PopCatalin 的答案(见下文),如果字典的值是值类型,我上面编写的代码将不起作用。如果我使用的是Dictionary<int, int>,那么我想使用的代码如下所示:

int i = dict[key] ?? default_value;

这不会编译,因为dict[key]它不是可为空的或引用类型。

4

6 回答 6

8

Dictionary<T>a和 a之间的区别在于HashtableaDictionary<T>是一种泛型类型,可以专门用于沿引用类型存储值类型。

哈希表只能存储引用类型(Object通过引用传递)和被装箱的值类型(也通过引用传递)。

当字典专门用于值类型时,它必须“按值”而不是通过引用返回这些值。因此,aDictionary<T>不能返回 null,因为 null不是值类型的有效值。

于 2008-12-30T03:13:01.640 回答
4

你的帖子有一个误解。字典不是 Hashtable 的包装器。这是一个完全不同的实现。

做出这种改变的原因主要是由一个断言来证明的:Null 是哈希表的有效值。如果没有此更改,则无法使用 [] 访问方法区分不存在的键和具有空值的值键。字典清除了这一点。

于 2008-12-30T01:28:07.967 回答
2

Dictionary.ContainsKey 可能比 TryGetValue 更适合您。

但至于为什么,不知道。

于 2008-12-30T01:28:13.130 回答
2

我为此写了一个扩展。

public static class DictionaryExtension
{
    public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> items, string key)
    {
        if (items != null && items.ContainsKey(key))
        {
            return items[key];
        }

        return default(TValue);
    }
}
于 2008-12-30T02:41:07.180 回答
1

如果您使用 Reflector 查看代码,您会看到 Dictionary 尝试找到键,如果找不到键,则会显式引发异常。

public TValue get_Item(TKey key)
{
    int index = this.FindEntry(key);
    if (index >= 0)
    {
        return this.entries[index].value;
    }
    ThrowHelper.ThrowKeyNotFoundException();
    return default(TValue);
}
于 2008-12-30T01:27:19.310 回答
0

我很确定这个限制是首先创建包装器的功能原因之一。

于 2008-12-30T01:25:51.607 回答