给定以下课程
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?
Equals
Foo
GetHashCode
为什么覆盖很重要GetHashCode?
是的,如果您的项目将用作字典中的键或HashSet<T>等,这很重要 - 因为它用于(在没有自定义的情况下IEqualityComparer<T>)将项目分组到存储桶中。如果两个项目的哈希码不匹配,它们可能永远不会被视为相等(永远不会调用Equals )。
HashSet<T>
IEqualityComparer<T>
GetHashCode()方法应该反映Equals逻辑;规则是:
Equals(...) == true
GetHashCode()
在这种情况下,看起来“ return FooId;”是一个合适的GetHashCode()实现。如果您正在测试多个属性,通常使用下面的代码将它们组合起来,以减少对角线冲突(即,与new Foo(3,5)具有不同的哈希码new Foo(5,3)):
return FooId;
new Foo(3,5)
new Foo(5,3)
在现代框架中,该HashCode类型具有帮助您从多个值创建哈希码的方法;在较旧的框架上,您需要不使用,例如:
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
==
!=``Equals``GetHashCode