C# 哈希函数用于字典查找
C# 哈希函数用于字典查找
给出以下类
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月22日
如果您的项将用作字典或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
时,您还可以考虑提供==
和!=
运算符。
示例和讨论链接看这里。