C# 我们如何使用 Object.GetHashCode()

26 浏览
0 Comments

C# 我们如何使用 Object.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的首选方法是什么?

为什么重写GetHashCode是重要的?

admin 更改状态以发布 2023年5月21日
0
0 Comments

实现GetHashCode()方法很难,因为除了Marc已经提到的规则之外,hash码在对象的生命周期内不应更改。因此,用于计算hash码的字段必须是不可变的。

在使用NHibernate时,我终于找到了解决此问题的方法。我的方法是从对象的ID计算hash码。ID只能通过构造函数设置,因此如果您想更改ID(这很不可能),您必须创建一个具有新ID和因此新hash码的新对象。这种方法最适合GUID,因为您可以提供一个无需参数的构造函数,该函数会随机生成一个ID。

0
0 Comments

如果你的项将用作字典或HashSet中的键,那么这很重要——因为在没有自定义的IEqualityComparer的情况下,这会将这些项分组到桶中。如果两个项的哈希码不匹配,它们可能永远不会被视为相等(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;
}

额外方便起见,你还可以提供 == != 运算符,以覆盖EqualsGetHashCode


当你做错了时会发生什么的演示,可以在这里找到。

0