如果在重载Equals()时没有重载GetHashCode(),会发生什么问题?

19

Jared Parsons的博客详细解释了实现相等性的方法以及为什么GetHashCode如此重要。正确实现相等性 - Jim H.
4个回答

9
最常见的方式是用于映射结构。
任何这样做的类在作为字典或哈希表的键时,其行为将是不可预测的。原因是实现使用GetHashCode和Equals来正确地在表中查找值。算法的简短版本如下:
1.通过桶的数量对HashCode取模,得到桶索引。 2.为指定的键和特定桶中的每个键调用.Equals()。 3.如果有匹配项,则为该值,否则没有匹配项=没有值。
未能保持GetHashCode和Equals同步将完全破坏此算法(以及其他许多算法)。

实现如何确定使用多少个桶?这是一个固定值吗? - Kyle Baran

1

将哈希/字典结构视为编号桶的集合。如果您总是将物品放在对应于它们的GetHashCode()的桶中,那么您只需要搜索一个桶(使用Equals())即可查看是否有东西存在。这有效,前提是您正在查找正确的桶。

因此,规则是:如果Equals()表示两个对象相等,则它们必须具有相同的GetHashCode()。


与其考虑编号桶,我认为更简单的方法是说哈希码用于避免比较。如果通过任何方式知道对象X的哈希码与对象Y的哈希码不匹配,则无需比较它们的其他任何内容。桶提供了一种简单的方法,使代码可以忽略那些哈希码显然无法等于某个特定值的项,但许多集合甚至会明确比较即使被排序到同一个桶中的项的哈希码。 - supercat

0

如果您不覆盖GetHashCode,那么比较您的对象的任何内容都可能出错。

正如所记录的,如果两个实例相等,则GetHashCode必须返回相同的值,因此希望测试它们是否相等的任何代码都可以使用GetHashCode作为第一步来分组可能相等的对象(因为它知道具有不同哈希码的对象不能相等)。如果您的GetHashCode方法为相等的对象返回不同的值,则它们可能在第一遍中进入不同的组,并且永远不会使用其Equals方法进行比较。

这可能会影响任何集合类型数据结构,但在基于哈希码的数据结构(例如字典和哈希集)中尤为棘手。

简而言之:当您覆盖Equals时,请始终覆盖GetHashCode,并确保它们的实现是一致的。


0
任何使用密钥的算法都将无法正常工作,假设它依赖于哈希键的预期行为。
两个相等的对象应该具有相同的哈希键值,但默认实现并不能保证这一点。

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