我有一个班,在三个花车中占有一席之地。我像这样覆盖了Equals:
return Math.Abs(this.X - that.X) < TOLERANCE
&& Math.Abs(this.Y - that.Y) < TOLERANCE
&& Math.Abs(this.Z - that.Z) < TOLERANCE;
这一切都很好,但现在我需要为这些顶点编写一个GetHashCode实现,而且我被卡住了。简单地取三个值的哈希码并将它们合并在一起就不够好了,因为位置略有不同的两个对象可能被认为是相同的。
那么,我如何为这个类构建一个GetHashCode实现,它将始终为上述方法认为相等的实例返回相同的值?
答案 0 :(得分:3)
我建议您重新考虑Equals
的实施。它违反了传递属性,这会让你头疼。请参阅How to: Define Value Equality for a Type,特别是此行:
if(x.Equals(y)&amp;&amp; y.Equals(z)) 返回true,然后x.Equals(z)返回 真正。这被称为传递 属性。
答案 1 :(得分:3)
只有一种方法可以满足GetHashCode
Equals
这样的要求。
假设你有这些物体(箭头表示容差的极限,我将其简化为1-D):
a c
<----|----> <----|---->
<----|---->
b
通过Equals
的实施,我们有:
a.Equals(b) == true
b.Equals(c) == true
a.Equals(c) == false
(这是提到的传递性的丧失......)
然而,the requirements of GetHashCode
are that Equals
being true implies that the hash codes are the same。因此,我们有:
hash(a) = hash(b)
hash(b) = hash(c)
∴ hash(a) = hash(c)
通过扩展,我们可以用这个覆盖1-D空间的任何部分(想象d
,e
,f
,...),所有的哈希都会有是一样的!
int GetHashCode()
{
return some_constant_integer;
}
我想说不要打扰.NET的GetHashCode
。它对您的应用程序没有意义。 ;)
如果您需要某种形式的哈希来快速查找数据类型,那么您应该开始查看某种spatial index。
答案 2 :(得分:1)
这个“等于”实现不满足相等的传递属性(如果X等于Y,Y等于Z,则X等于Z)。
鉴于您已经有一个不合规的Equals实现,我不会太担心您的散列代码。
答案 3 :(得分:1)
这可能吗?在你的等式实现中,实际上有一个滑动窗口,其中相等性被认为是真的,但是如果你必须为一个散列“bucketize”(或量化),那么两个“相等”的项可能位于哈希“边界”。