为什么在重写 Equals 方法时重写 GetHashCode 很重要? [英] Why is it important to override GetHashCode when Equals method is overridden?
问题描述
给定以下类
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 Foo
s 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 forGetHashCode()
- if the
GetHashCode()
is equal, it is not necessary for them to be the same; this is a collision, andEquals
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;
}
哦 - 为方便起见,您还可以考虑在覆盖 Equals
和 GetHashCode
时提供 ==
和 !=
运算符代码>.
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屋!