C# 我们如何使用 Object.GetHashCode()
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日
如果你的项将用作字典或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; }
额外方便起见,你还可以提供 ==
和!=
运算符,以覆盖Equals
和GetHashCode
。
当你做错了时会发生什么的演示,可以在这里找到。