首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当Equals方法被覆盖时,为什么覆盖GetHashCode很重要?

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

Stack Overflow用户
提问于 2008-12-16 21:41:18
回答 15查看 417.1K关注 0票数 1.6K

给定以下类

代码语言: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表示Foo表的一行。哪种方法是覆盖GetHashCode的首选方法

为什么覆盖GetHashCode很重要

EN

回答 15

Stack Overflow用户

回答已采纳

发布于 2008-12-16 21:47:49

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

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

如果两个事物相等(Equals(...) == true),则它们必须返回相同的值。

  • 是相等的,它们没有必要相同;这是一个冲突,将调用Equals以查看它是否为真正的相等。

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

代码语言:javascript
运行
复制
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时,您还可以考虑提供==!=运算符。

here演示了当你弄错的时候会发生什么。

票数 1.4K
EN

Stack Overflow用户

发布于 2008-12-21 12:39:21

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

当我使用NHibernate时,我终于找到了这个问题的解决方案。我的方法是根据对象的ID计算哈希码。ID只能通过构造函数来设置,所以如果您想要更改ID (这是非常不可能的),您必须创建一个具有新ID的新对象,从而创建一个新的哈希码。这种方法最适合GUID,因为您可以提供一个随机生成ID的无参数构造函数。

票数 151
EN

Stack Overflow用户

发布于 2008-12-16 13:48:38

通过重写Equals,您基本上是在声明您更了解如何比较给定类型的两个实例,因此您很可能是提供最佳散列代码的最佳候选者。

这是一个ReSharper如何为您编写GetHashCode()函数的示例:

代码语言:javascript
运行
复制
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;
    }
}

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

票数 70
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/371328

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档