4 回答
TA贡献1719条经验 获得超6个赞
是的,重要的是,您的项目将用作字典中的键,或者HashSet<T>
等等 - 因为这是用于(在没有自定义的情况下IEqualityComparer<T>
)将项目分组到存储桶中。如果两个项的哈希码不匹配,它们可能永远不会被认为是相等的(Equals
将永远不会被调用)。
该GetHashCode()
方法应反映Equals
逻辑; 规则是:
如果两个东西相等(
Equals(...) == true
)那么它们必须返回相同的值GetHashCode()
如果
GetHashCode()
是相等的,它是不必要对他们是相同的; 这是一次碰撞,Equals
将被调用以查看它是否是真正的平等。
在这种情况下,看起来“ return FooId;
”是一个合适的GetHashCode()
实现。如果您正在测试多个属性,通常使用下面的代码组合它们,以减少对角线冲突(即,new Foo(3,5)
具有不同的哈希码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
。
当你弄错了会发生什么事的证明就在这里。
TA贡献1893条经验 获得超10个赞
实际上很难GetHashCode()
正确实现,因为除了Marc已经提到的规则之外,哈希代码在对象的生命周期内不应该改变。因此,用于计算哈希码的字段必须是不可变的。
当我使用NHibernate时,我终于找到了解决这个问题的方法。我的方法是从对象的ID计算哈希码。只能通过构造函数设置ID,因此如果要更改ID,这是非常不可能的,您必须创建一个具有新ID的新对象,因此需要新的哈希代码。这种方法最适用于GUID,因为您可以提供随机生成ID的无参数构造函数。
TA贡献1946条经验 获得超4个赞
通过重写Equals,您基本上声明自己是更了解如何比较给定类型的两个实例的人,因此您很可能是提供最佳哈希码的最佳候选者。
这是ReSharper如何为您编写GetHashCode()函数的示例:
public override int GetHashCode(){ unchecked { var result = 0; result = (result * 397) ^ m_someVar1; result = (result * 397) ^ m_someVar2; result = (result * 397) ^ m_someVar3; result = (result * 397) ^ m_someVar4; return result; }}
正如您所看到的,它只是试图根据类中的所有字段猜测一个好的哈希代码,但是既然您知道对象的域或值范围,您仍然可以提供更好的哈希代码。
- 4 回答
- 0 关注
- 866 浏览
添加回答
举报