【问题标题】:How to write a hashcode generator for this class?如何为此类编写哈希码生成器?
【发布时间】:2010-06-28 00:40:20
【问题描述】:

我有一个类在三个浮点数中占有一席之地。我已经像这样覆盖了 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 实现,它总是为上述方法认为相等的实例返回相同的值?

【问题讨论】:

  • 感谢那些指出 equals 不是传递的人。我应该看到的!

标签: c# hash


【解决方案1】:

只有一种方法可以像这样使用Equals 来满足GetHashCode 的要求。

假设您有这些对象(箭头表示公差的限制,我将其简化为一维):

     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)

通过扩展,我们可以用这个覆盖一维空间的任何部分(想象def,...),所有的哈希都必须相同!

int GetHashCode()
{
    return some_constant_integer;
}

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

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

【讨论】:

  • 我会接受这个,因为它确实回答了这个问题(即使这个问题问得非常糟糕)
【解决方案2】:

我建议您重新考虑您对Equals 的实现。它违反了传递性,这会让你在路上头疼。请参阅How to: Define Value Equality for a Type,特别是这一行:

if (x.Equals(y) && y.Equals(z)) 返回 true,然后 x.Equals(z) 返回 真的。这被称为传递 属性。

【讨论】:

    【解决方案3】:

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

    鉴于您已经有一个不符合标准的 Equals 实现,我不会太担心您的哈希代码。

    【讨论】:

      【解决方案4】:

      这可能吗?在您的相等实现中,实际上存在一个滑动窗口,在该窗口中相等被认为是正确的,但是如果您必须为哈希“分桶”(或量化),那么“相等”的两个项目可能位于哈希“边界”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-15
        • 1970-01-01
        • 1970-01-01
        • 2016-07-09
        • 2014-12-31
        • 1970-01-01
        相关资源
        最近更新 更多