为什么字典不能像哈希表那样访问不存在的键?

5
如果我正在使用 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]不是可空的或引用类型。

6个回答

8
Dictionary<T>Hashtable的区别在于,Dictionary<T>是一种可以专门用于存储值类型和引用类型的泛型类型。

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

当字典用值类型进行特化时,它必须通过“按值”而不是通过引用返回这些值。因此,Dictionary<T>无法返回null,因为对于值类型来说,null不是有效值


4

您的帖子中有一个误解。字典不是Hashtable的包装器,而是完全不同的实现。

这个改变的原因主要是基于这样一种断言:null是哈希表的一个有效值。如果没有这个改变,就无法使用[]方法来区分不存在的键和值为空的键。字典澄清了这一点。


+1 是因为我从未查过字典而没有在找不到我要找的单词时说“WTF?” - Peter T. LaComb Jr.
JaredPar,如果我在Reflector中检查System.Collections.DictionaryBase,我发现它使用Hashtable作为其底层数据结构。我看错了吗? - Robert Rossney
1
我来回答自己的问题:Dictionary<TKey, TValue>并不是从DictionaryBase派生的。我不知道为什么我那么确定它是,但我错了。 - Robert Rossney

2

使用Dictionary.ContainsKey可能比TryGetValue更适合您的需求。

至于为什么,我不清楚。


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);
    }
}

1

如果你使用Reflector查看代码,你会发现字典试图查找关键字,如果没有找到,则显式地引发异常。

public TValue get_Item(TKey key)
{
    int index = this.FindEntry(key);
    if (index >= 0)
    {
        return this.entries[index].value;
    }
    ThrowHelper.ThrowKeyNotFoundException();
    return default(TValue);
}

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接