一尘不染

为什么在重写 Equals 方法时重写 GetHashCode 很重要?

javascript

给定以下课程

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


阅读 142

收藏
2022-02-22

共1个答案

一尘不染

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

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

  • 如果两件事相等(Equals(...) == true),那么它们必须返回相同的值GetHashCode()
  • 如果GetHashCode()相等,则它们不必相同;这是一个冲突,Equals将被调用以查看它是否是一个真正的平等。

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

在现代框架中,该HashCode类型具有帮助您从多个值创建哈希码的方法;在较旧的框架上,您需要不使用,例如:

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;
}

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

2022-02-22