为什么.NET词典会发牢骚?

Mar*_*rio 3 .net vb.net dictionary

在.NET中,如果您向字典询问与其没有的键相关联的值,则会引发异常.你可以通过电话来解决这个问题,TryGetValue但我发现它使用了令人厌恶的Ref var.

这意味着你通常必须通过首先检查密钥是否存在来防止丢失密钥(ContainsKey)这看起来很麻烦.

在Ruby中,如果您向哈希询问与键相关联的值,则不会出现异常.它只会返回一些默认值,您可以根据需要更改.这使得使用哈希更加愉快.

有没有什么理由可以解释为什么.NET字典会因缺少密钥而烦恼呢?

Jar*_*Par 12

问题是默认值根本不是密钥不在字典中的确定答案.例如,在.Net中,类的默认值是null.对于任何ref类型,这是一个完全可接受的值,因此可以用作键.

Dictionary<int, string> map = ...;
map.Add(42, null);  // OK
Run Code Online (Sandbox Code Playgroud)

让我们假设Dictionary<TKey, TValue>在缺少密钥时确实返回了默认值.在那个世界中,以下代码将失败

void FillValue(Dictionary<int, string> map, int value) { 
  if (map[value] == null) {  
    map.Add(value, "");
  }
}
Run Code Online (Sandbox Code Playgroud)

value在具有值的字典中已存在的情况下,此代码将失败null.它会抛出因为Add要求值不存在才能正确执行.

底线是,默认值表示缺少的情况会在代码中产生不可避免的歧义.目前的设计Dictionary<TKey, TValue>尽可能避免歧义

另请注意,设计符合Hashtable您的建议(缺失值返回null)..Net脱离了这种设计,部分原因是它产生了歧义问题.

  • @Mario当然你总是可以在那个场景中使用`ContainsKey`但是你需要支付两次查询费用(一次用于`ContainsKey`,另一次用于`[]`).`TryGetValue`执行两个操作,只支付查询成本一次.字典中的查找力图是O(1),但即使O(1)也不意味着"即时".这通常是一项非常复杂的操作 (2认同)
  • @Neolisk我实际上发现了太多与双重查找相关的性能问题.它们通常不是瓶颈,但有几次我通过删除双重查找将场景减少了5-15%. (2认同)