2010-06-28 86 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

這可能嗎?在你的平等實現中,實際上有一個滑動窗口,在這個窗口內平等被認爲是真實的,但是如果你不得不爲「散列」(或量化)散列,那麼兩個「相等」的項目可能位於散列「邊界」。