一尘不染

当覆盖Equals方法时,覆盖GetHashCode为什么很重要?

c#

鉴于以下课程

public class Foo
{
    public int FooId { get; set; }
    public string FooName { get; set; }

    public override bool Equals(object obj)
    {
        Foo fooItem = obj as Foo;

        if (fooItem == null) 
        {
           return false;
        }

        return fooItem.FooId == this.FooId;
    }

    public override int GetHashCode()
    {
        // Which is preferred?

        return base.GetHashCode();

        //return this.FooId.GetHashCode();
    }
}

我重写了该Equals方法,因为Foo代表Foos表的一行。哪种方法可以覆盖GetHashCode

为什么覆盖很重要GetHashCode


阅读 223

收藏
2020-05-19

共1个答案

一尘不染

是的,将您的项目用作字典或HashSet<T>等等中的键非常重要-
因为它用于(在没有custom的情况下IEqualityComparer<T>)将项目分组到存储桶中。如果两个项目的哈希码不匹配,则可能 永远不会
认为它们相等(永远不会调用等于)。

所述的GetHashCode()方法应该反映Equals逻辑;
规则是:

  • 如果两个事物相等(Equals(...) == true),则它们 必须 返回相同的值GetHashCode()
  • 如果GetHashCode()是相等的,它是 必要对他们是相同的; 这是一次碰撞,Equals将调用它来查看它是否是真正的相等性。

在这种情况下,看起来“ return FooId;”是合适的GetHashCode()实现。如果您要测试多个属性,通常使用如下代码将它们组合在一起,以减少对角线冲突(即,new Foo(3,5)与的哈希码不同new Foo(5,3)):

unchecked // only needed if you're compiling with arithmetic checks enabled
{ // (the default compiler behaviour is *disabled*, so most folks won't need this)
    int hash = 13;
    hash = (hash * 7) + field1.GetHashCode();
    hash = (hash * 7) + field2.GetHashCode();
    ...
    return hash;
}

哦,为方便起见,在覆盖和时,您也可以考虑提供==!=运算符。Equals``GetHashCode


当你得到这个错误会发生什么情况的演示是在这里

2020-05-19