如何为这个类编写哈希码生成器?

时间:2010-06-28 00:40:21

标签: c# hash

我有一个班,在三个花车中占有一席之地。我像这样覆盖了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实现,它将始终为上述方法认为相等的实例返回相同的值?

4 个答案:

答案 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空间的任何部分(想象def,...),所有的哈希都会有是一样的!

int GetHashCode()
{
    return some_constant_integer;
}

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

如果您需要某种形式的哈希来快速查找数据类型,那么您应该开始查看某种spatial index

答案 2 :(得分:1)

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

鉴于您已经有一个不合规的Equals实现,我不会太担心您的散列代码。

答案 3 :(得分:1)

这可能吗?在你的等式实现中,实际上有一个滑动窗口,其中相等性被认为是真的,但是如果你必须为一个散列“bucketize”(或量化),那么两个“相等”的项可能位于哈希“边界”。