代码之家  ›  专栏  ›  技术社区  ›  Martin

如何为此类编写哈希代码生成器?

  •  2
  • Martin  · 技术社区  · 14 年前

    我有一个班在三个浮球上有一个位置。我重写了等号,就像这样:

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

    This is all very well, but now I need to write a GetHashCode implementation for these vertices, and I'm stuck. simply taking the hashcode of the three values and xoring them together isn't good enough, because two objects with slightly different positions may be considered the same.

    那么,我如何为这个类构建一个gethashcode实现,这个类总是为上述方法认为相等的实例返回相同的值?

    4 回复  |  直到 14 年前
        1
  •  3
  •   porges    14 年前

    只有一种方法可以满足 GetHashCode 用一个 Equals 这样地。

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

         a                c
    <----|---->      <----|---->
            <----|---->
                 b
    

    通过你的实施 等于 我们有:

    a.Equals(b) == true
    b.Equals(c) == true
    
    a.Equals(c) == false
    

    (This is the loss of transitivity mentioned...)

    然而, 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)
    

    通过扩展,我们可以用它覆盖一维空间的任何部分(想象一下 d , e , f ,…),所有哈希值都必须相同!

    int GetHashCode()
    {
        return some_constant_integer;
    }
    

    我会说,不要为.NET的 方法 . 这对您的应用程序没有意义。;)

    If you needed some form of hash for quick lookup for your data type, you should start looking at some kind of spatial index .

        2
  •  3
  •   Michael Petrotta user3140870    14 年前

    我建议您重新考虑 Equals . 它侵犯了可传递的属性,这会让你在路上头疼。见 How to: Define Value Equality for a Type 尤其是这条线:

    如果(x.equals(y)&y;y.equals(z)) 返回true,然后x.equals(z)返回 真的。这叫做传递 财产。

        3
  •  1
  •   Anon.    14 年前

    这个“等于”的实现不满足相等的传递属性(如果x等于y,y等于z,那么x等于z)。

    Given that you've already got a non-conforming implementation of Equals, I wouldn't worry too much about your hashing code.

        4
  •  1
  •   spender    14 年前

    这有可能吗?在您的等式实现中,实际上有一个滑动窗口,在这个窗口中等式被认为是真的,但是如果您必须对散列进行“bucketize”(或量化),那么“equal”的两个项可能位于散列“boundary”的任一侧。