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

鉴于以下课程

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

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

        return fooItem.FooId == this.FooId;
    }

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

        return base.GetHashCode();

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

我已经覆盖了Equals方法,因为Foo代表的一排Foo桌上。 哪个是重写GetHashCode的首选方法?

为什么重写GetHashCode很重要?


是的,如果您的项目将用作字典中的键或HashSet<T>等,这一点非常重要,因为这用于(在没有自定义IEqualityComparer<T> )将项目分组为桶。 如果两个项目的哈希码不匹配,它们可能永远不会被视为相等( Equals将永远不会被调用)。

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

  • 如果两个事物相等( Equals(...) == true ),那么它们必须为GetHashCode()返回相同的值
  • 如果GetHashCode()是相等的,则它们不必是相同的; 这是一次碰撞, Equals将被调用以查看它是否是真正的平等。
  • 在这种情况下,它看起来像“ return FooId; ”是一个合适的GetHashCode()实现。 如果您正在测试多个属性,通常使用下面的代码将它们组合起来以减少对角线冲突(即使new Foo(3,5)具有与new Foo(5,3)不同的散列码):

    int hash = 13;
    hash = (hash * 7) + field1.GetHashCode();
    hash = (hash * 7) + field2.GetHashCode();
    ...
    return hash;
    

    哦 - 为了方便起见,当重写EqualsGetHashCode时,您可能还会考虑提供==!=运算符。


    当你发现这个错误时会发生什么的证明就在这里。


    实际上很难正确实现GetHashCode() ,因为除了Marc已经提到的规则之外,哈希代码在对象的生命周期中不应该改变。 因此,用于计算哈希代码的字段必须是不可变的。

    当我使用NHibernate时,终于找到了解决这个问题的办法。 我的方法是从对象的ID中计算哈希码。 ID只能通过构造函数设置,所以如果你想改变ID,这是不太可能的,你必须创建一个新的对象,它有一个新的ID,因此一个新的哈希码。 这种方法最适合于GUID,因为您可以提供一个随机生成ID的无参数构造函数。


    通过覆盖Equals,你基本上声明你是一个知道如何比较给定类型的两个实例的人,所以你很可能是提供最佳散列码的最佳人选。

    这是ReSharper如何为你写一个GetHashCode()函数的例子:

    public override int GetHashCode()
    {
        unchecked
        {
            var result = 0;
            result = (result * 397) ^ m_someVar1;
            result = (result * 397) ^ m_someVar2;
            result = (result * 397) ^ m_someVar3;
            result = (result * 397) ^ m_someVar4;
            return result;
        }
    }
    

    正如你所看到的,它只是试图根据类中的所有字段猜测一个好的哈希码,但由于你知道你的对象的域或值范围,你仍然可以提供更好的哈希码。

    链接地址: http://www.djcxy.com/p/6771.html

    上一篇: Why is it important to override GetHashCode when Equals method is overridden?

    下一篇: Utilizing the GetHashCode() part of IEqualityComparer<T> for direct comparisons?