我应该何时为我的类型定义哈希码函数?

时间:2010-06-13 21:16:15

标签: c# java

除了允许好好使用哈希表之外,还有其他原因为我的类型实现哈希码函数吗?

假设我正在设计一些我打算在内部使用的类型。我知道类型是系统的“内部”,我也知道我永远不会在哈希表中使用这些类型。尽管如此,我还是决定重新定义equals()方法。

理论说我也应该重新定义哈希码方法,但我看不出任何理由,在这种情况下,我应该这样做。

任何人都可以指出任何其他原因吗?

这个问题可以改为:在哪种情况下我们应该在我们的类型中实现哈希码方法。

PS:我不是问如何实施一个。我问何时

4 个答案:

答案 0 :(得分:10)

可能没有 - 但是你的任何代码都会使用LINQ吗?有许多意外的地方可能会在您的数据上使用散列图或字典。

如果您不想要意外......“有趣”,那么如果您更改Equals,请覆盖GetHashCode。同样,任何IEquatable<T>.Equals都应与object.Equals实施相匹配。

答案 1 :(得分:6)

是的,当然。 hashCode和equals是同一个东西的2个视图,必须保持一致。集合中的许多例程使用哈希码,如果它告诉与等号不同的东西,则会开始行为不端。你可以把“行为不端”看作“非常难以找到导致早期脱发的虫子”。

如果你重写等于,你必须覆盖哈希码,不是因为指南这样说,而是因为你重视你的头发(或时间)。

现代IDE为您生成良好的equals / hashcode,Java Commons或Spring的EqualsBuilder / HashCodeBuilder可以帮助您轻松实现。 Lombok项目即时生成它们。

这是非常严肃的事情,你可以用这些方法做到最好是做对了,有数百种方法做错了,导致痛苦和痛苦。如果您可以避免自己编写,请使用生成器或库来帮助您。

答案 2 :(得分:4)

  

在哪种情况下我们应该在我们的类型中实现哈希码方法。

简短回答:每当你覆盖.Equals时。因为框架设计指南是这样说的。

答案 3 :(得分:0)

如果您确定您的对象不会在哈希表中使用并且未使用哈希码,那么您可以覆盖hashCode以抛出“未实现”的异常。这比不覆盖更安全,因为它明确禁止使用该方法,并避免否则会导致显着的错误。它还将清楚地向您显示该方法是否实际使用。

但是,我个人会说,只需使用IDE生成一个与Equals一致的合理实现,并完成它。它通常是覆盖等于的值类型,并且在测试这些时,通常使用映射,因此实现equals / hashcode api所需的完整契约是有意义的。