为什么在重写 Equals 方法时重写 GetHashCode 很重要? [英] Why is it important to override GetHashCode when Equals method is overridden?

查看:24
本文介绍了为什么在重写 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;

        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 代表 Foo 表的一行.哪个是覆盖 GetHashCode 的首选方法?

I have overridden the Equals method because Foo represent a row for the Foos table. Which is the preferred method for overriding the GetHashCode?

为什么覆盖 GetHashCode 很重要?

Why is it important to override GetHashCode?

推荐答案

是的,如果您的项目将用作字典中的键,或者 HashSet 等,这一点很重要 -因为这用于(在没有自定义 IEqualityComparer 的情况下)将项目分组到桶中.如果两个项目的哈希码不匹配,它们可能永远被认为是相等的 (Equals 将永远不会被调用.

Yes, it is important if your item will be used as a key in a dictionary, or HashSet<T>, etc - since this is used (in the absence of a custom IEqualityComparer<T>) to group items into buckets. If the hash-code for two items does not match, they may never be considered equal (Equals will simply never be called).

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

The GetHashCode() method should reflect the Equals logic; the rules are:

  • 如果两件事相等 (Equals(...) == true) 那么它们必须GetHashCode()
  • 如果GetHashCode() 相等,则它们不必相同;这是一个碰撞,Equals 将被调用以查看它是否是真正的相等.
  • if two things are equal (Equals(...) == true) then they must return the same value for GetHashCode()
  • if the GetHashCode() is equal, it is not necessary for them to be the same; this is a collision, and Equals will be called to see if it is a real equality or not.

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

In this case, it looks like "return FooId;" is a suitable GetHashCode() implementation. If you are testing multiple properties, it is common to combine them using code like below, to reduce diagonal collisions (i.e. so that new Foo(3,5) has a different hash-code to 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;
}

哦 - 为方便起见,您还可以考虑在覆盖 EqualsGetHashCode 时提供 ==!= 运算符代码>.

Oh - for convenience, you might also consider providing == and != operators when overriding Equals and GetHashCode.

当你弄错时会发生什么的演示是 这里.

A demonstration of what happens when you get this wrong is here.

这篇关于为什么在重写 Equals 方法时重写 GetHashCode 很重要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆