2010-06-28 84 views
2

我有一个班级,在三个浮标中占有一席之地。我已重写的Equals像这样:如何为这个类写一个哈希码生成器?

return Math.Abs(this.X - that.X) < TOLERANCE 
    && Math.Abs(this.Y - that.Y) < TOLERANCE 
    && Math.Abs(this.Z - that.Z) < TOLERANCE; 

这一切都非常好,但现在我需要编写这些顶点的GetHashCode的实现,和我被困。简单地将三个值的哈希码和xoring在一起是不够好的,因为两个位置略有不同的对象可能被认为是相同的。

那么,我该如何为这个类建立一个GetHashCode实现,它总是会为上面的方法认为相等的实例返回相同的值?

+0

感谢指出平等不是传递性的人。我应该看到的! – Martin 2010-06-28 00:49:58

回答

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空间的任何部分(想象def,...),并且所有的哈希值将是相同!

int GetHashCode() 
{ 
    return some_constant_integer; 
} 

我会说不要打扰.NET的GetHashCode。它对你的应用程序没有意义。;)

如果你需要某种形式的散列来快速查找你的数据类型,你应该开始查找某种spatial index

+0

我打算接受这个问题,因为它确实回答了这个问题(即使问题真的很严重) – Martin 2010-06-28 14:13:09

1

这个“Equals”实现不满足等于(即如果X等于Y,且Y等于Z,则X等于Z)的传递性质。

鉴于您已经获得了Equals的不合规实现,我不会过分担心您的哈希代码。

3

我建议您重新考虑执行Equals。它违反了传递性财产,这会让你头痛不已。见How to: Define Value Equality for a Type,具体这一行:

如果(x.Equals(y)的& & y.Equals(Z)) 返回true,那么x.equals(z)返回 真。这被称为传递性的 属性。

1

这可能吗?在你的平等实现中,实际上有一个滑动窗口,在这个窗口内平等被认为是真实的,但是如果你不得不为“散列”(或量化)散列,那么两个“相等”的项目可能位于散列“边界”。