正确实施 GetHashCode [重复]

Posted

技术标签:

【中文标题】正确实施 GetHashCode [重复]【英文标题】:Implementing GetHashCode correctly [duplicate] 【发布时间】:2012-02-19 01:16:24 【问题描述】:

我想听听社区的意见,我应该如何为我的对象实现 GetHashCode(或覆盖它)。我知道如果我覆盖 equals 方法,我需要这样做。我已经实现了很多次,有时只是调用基本方法。我知道如果我的对象包含相同的详细信息(成员),它应该等于该对象的另一个实例。从班级成员那里获取哈希码的最佳方法是什么?

【问题讨论】:

考虑作为***.com/a/720282/93922的副本关闭 在做这件事之前,我建议你阅读并理解我关于它的文章:blogs.msdn.com/b/ericlippert/archive/2011/02/28/… 谢谢,我知道这可能是一个常见问题,我应该多做一点。感谢您的帮助 @Fildor:在这里:ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode @EricLippert 太棒了,谢谢! 【参考方案1】:

假设您的班级如下所示:

class Frob 
    public string Foo  get; set; 
    public int Bar  get; set; 
    public double FooBar  get; set; 

假设您定义了 equals,如果 FooBar 相等,则 Frob 的两个实例相等,但 FooBar 无关紧要。

那么您应该根据FooBar 来定义GetHashCode。一种方法是这样的:

return this.Foo.GetHashCode() * 17 + this.Bar.GetHashCode();

基本上,您只想合并定义相等性的所有字段。一种方法是像我所做的那样不断累积并乘以 17。它快速、简单、正确,而且通常可以提供良好的分布。

【讨论】:

我觉得这本身应该是一个问题,但为什么是 23? 也许会指出 GetHashCode 只告诉你两个对象是否可能被认为是相等的。仍然存在哈希冲突的可能性。 在实现GetHashCode()(和Equals())时要小心,因为它依赖于可变数据,就像这里一样。如果您将此类对象放入基于哈希的字典中,然后对其进行变异,则该字典将不再正常工作。理想情况下,GetHashCode()(和Equals())应该只依赖于不可变数据。 我认为计算应该用 unchecked 关键字包装,就像这样:unchecked(this.Foo.GetHashCode() * 17 + this.Bar.GetHashCode())。总和可能大于 int.MaxValue。 @Quintus:我的立场是正确的。当分配Bar = int.MaxValue; Foo = "something",运行GetHashCode()函数并且没有unchecked关键字时,代码将运行并产生一个负哈希码并且不会崩溃,所以unchecked关键字不是必需的

以上是关于正确实施 GetHashCode [重复]的主要内容,如果未能解决你的问题,请参考以下文章

实现 GetHashCode [重复]

自定义类型 GetHashCode [重复]

C#GetHashCode() 高性能散列算法 [重复]

覆盖 GetHashCode [重复]

在 C# 中实现 Equals 但不是 GetHashCode [重复]

为啥我需要覆盖 C# 中的 .Equals 和 GetHashCode [重复]