如何正确地重写 object.GetHashCode():一些通用建议和指南。

50
根据MSDN,哈希函数必须具备以下特性:
  1. 如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值。但是,如果两个对象不相等,则它们的GetHashCode方法不一定要返回不同的值。

  2. 对象的GetHashCode方法必须在对象状态没有更改决定Equals方法的返回值的情况下一致地返回相同的哈希码。请注意,这仅适用于当前应用程序的执行,并且如果再次运行该应用程序,则可能返回不同的哈希码。

  3. 为了获得最佳性能,哈希函数必须对所有输入生成随机分布。


我经常遇到以下情况:我创建了一个类,实现了IEquatable<T>并重写了object.Equals(object)。MSDN指出:

覆盖Equals的类型也必须覆盖GetHashCode;否则,Hashtable可能无法正常工作。

然后我通常会卡住一些东西。因为如何正确地重写object.GetHashCode()?我从未真正知道从哪里开始,似乎有很多陷阱。 在StackOverflow这里,有很多与GetHashCode覆盖相关的问题,但大多数似乎都是关于相当特定的情况和具体问题。因此,我希望在这里获得一个好的编译。一个具有一般建议和指南的概述。该做什么、不该做什么、常见陷阱、从哪里开始等等。 我希望它特别针对C#,但我认为其他.NET语言也应该差不多吧(?)。

我认为最好的方法是每个主题创建一个答案,首先提供快速简短的答案(如果可能最好接近一行),然后可能提供更多信息,并以相关问题、讨论、博客文章等结束。如果有的话,那么我可以创建一个帖子作为已接受的答案(将其置于顶部),只包含“目录”。尽量保持简短明了。不要仅链接到其他问题和博客文章。试着摘取它们的精髓,然后链接到源代码(特别是因为源代码可能会消失)。此外,请尝试编辑和改进答案,而不是创建很多非常相似的答案。

我不是一个非常好的技术作家,但至少我会尝试格式化答案,使它们看起来像,创建目录等等。我还会尝试在这里搜索一些相关的问题,回答其中的一些部分,并可能摘出我能够处理的精髓。但由于我在这个主题上不是非常稳定,所以大部分时间我会尽量避免 :p

11个回答

-2
public override int GetHashCode()
{
    return IntProp1 ^ IntProp2 ^ StrProp3.GetHashCode() ^ StrProp4.GetHashCode ^ CustomClassProp.GetHashCode;
}

在 customClass 的 GetHasCode 方法中做同样的事情。非常好用。

为什么?背后的理论是什么?你如何确信它“像魔法一样”有效? - Johann Gerell
我认为的假设是,微软在String类中正确地实现了GetHashCode()方法,由于它们的哈希码是唯一的,因此该操作也应返回唯一值。 - Richard Clayton
1
这种方法的问题在于相等的属性会产生相同的哈希码。当你异或那些哈希码时,你得到的是 0。示例:http://ideone.com/vndV1H - Matthijs Wessels

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