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

Dictionary does not contain key despite Comparer.Equals returning true

我一直在寻找一个错误,我有一个字典坚持说一个键不存在,尽管它的比较器实际上说它存在。例如,在下面的片段中,抛出异常:

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>,带有默认的相等比较器(空构造函数)。 TKey class 实现了正确的 GetHashCodeEquals 方法。

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

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

事情是这样发生的:

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