【问题标题】:Why doesn't a Dictionary access nonexistent keys like a Hashtable does?为什么字典不像 Hashtable 那样访问不存在的键?
【发布时间】:2010-09-28 19:04:45
【问题描述】:

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

【问题讨论】:

    标签: c# .net dictionary hashtable


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • +1 因为我从来没有查过字典也没有说“WTF?”当我没有找到我要找的词时。
      • JaredPar,如果我在 Reflector 中检查 System.Collections.DictionaryBase,我发现它使用 Hashtable 作为其底层数据结构。我看错了吗?
      • 我会回答我自己的问题:Dictionary 不是从 DictionaryBase 派生的。我不知道为什么我如此确定它确实如此,但我错了。
      【解决方案3】:

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

      但至于为什么,不知道。

      【讨论】:

        【解决方案4】:

        我为此写了一个扩展。

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

        【讨论】:

          【解决方案5】:

          如果您使用 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);
          }
          

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-11-25
              • 2016-02-11
              • 2011-10-11
              • 1970-01-01
              • 2010-09-23
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多