尽管 Comparer.Equals 返回 true,但字典不包含键

Dictionary does not contain key despite Comparer.Equals returning true

提问人:Lazlo 提问时间:1/31/2018 更新时间:1/31/2018 访问量:295

问:

我一直在寻找一个错误,我有一本字典坚持说一个键不存在,尽管它的比较器实际上说它确实存在。例如,在以下代码片段中,将引发异常:

if (!dictionary.ContainsKey(key))
{
    var comparer = dictionary.Comparer;

    foreach (var _key in dictionary.Keys)
    {
        if (comparer.Equals(key, _key) &&
            comparer.Equals(_key, key) &&
            comparer.GetHashCode(key) == comparer.GetHashCode(_key) &&
            comparer.GetHashCode(_key) == comparer.GetHashCode(key))
        {
            throw new Exception("Key exists, but dictionary doesn't find it");
        }
    }
}

字典是具有默认相等比较器(空构造函数)的泛型。该类实现适当的 和方法。Dictionary<TKey, TValue>TKeyGetHashCodeEquals

我在这里可能遗漏了什么吗?我完全不知所措!

C# .NET 字典 相等

评论

1赞 1/31/2018
将哈希码添加到字典后是否发生了变化?
1赞 Olivier Jacot-Descombes 1/31/2018
哪种类型的钥匙?
1赞 Alexei Levenkov 1/31/2018
像往常一样,真正的最小可重现示例会暴露问题......stackoverflow.com/questions/3007296/......可能被认为是重复的。

答:

8赞 Sergey Kalinichenko 1/31/2018 #1

发生这种情况的唯一方法是,如果键是可变的,并且其内容在插入字典后已更改。

这是如何发生的:

  • 将键插入字典;字典获取其哈希码,并将其放入相应的哈希桶中,通过调用Equals
  • 你改变了密钥;现在,它的哈希代码不再与其哈希桶对应
  • 你打电话给.字典在其新存储桶中查找键。由于密钥不存在,因此被报告ContainsKeyfalse
  • 当您迭代字典时,将返回所有键,包括不再位于其合法存储桶中的键。这就是为什么你会在循环中受到打击。foreach

评论

0赞 Lazlo 1/31/2018
确实如此! 依赖于可变属性。这让我发疯了,谢谢!GetHashCode