2012-09-21 99 views
1

我被一個看似簡單的問題困住了。我有兩個對象,我正在比較!=。哈希碼相同,但!=返回true?

當我運行該應用程序時,a!= b爲真。 當我放置斷點並執行Watch時,a.GetHashCode()== b.GetHashCode()爲true。

這兩個(引用類型)對象在不同的​​程序集中定義,但我找不到對!=方法的重寫(儘管GetHashCode被重寫)。對此有另一種解釋嗎?有可能兩個對象的GetHashCode可能是相同的,但是一個not-overriden!=會返回true?

謝謝。

回答

6

當兩個不同的對象返回相同的代碼時,它被稱爲「碰撞」。只有大約40億個可能的整數值,以及超過40億個[你的班級名稱]的可能值,一些衝突是不可避免的。這就是爲什麼基於散列的結構(即Dictionary)不能完全依賴於GetHashCode,它還需要一個合理的實現纔能有效。 Equals方法是用於解決這些衝突的方法。

當然,類的創建者也可能覆蓋GetHashCodeEquals,並且在某種程度上犯了一個錯誤,以某種方式違反了生成哈希碼的「合同」。 Here是創建GetHashCode方法時要牢記的一條準則列表。請記住,有一小部分事情要做,而另一組事情可以通過高效地工作來實現。

return 0;實際上是一個完全可以接受的GetHashCode實現。它符合所有的規則,它只有100%的機率造成衝突,所以它將是非常低效的,你永遠不應該這樣做。

+0

如果在調試散列算法時碰巧遇到碰撞,那麼最有可能極其糟糕。 – Magnus

+0

@Magnus完全取決於情況。他們是否創建了兩個發生碰撞的對象(可能性是40億分之一),還是創建了很多對象,並假定哈希代碼是唯一的,並且其代碼因此而中斷?在第二種情況下,賠率是'numberOfGeneratedObjects /〜40億' – Servy

+1

確定你是對的。順便說一下,40億分之一的人認爲使用了一種完美的哈希算法,但事實上,其可能性要低得多。 (除非數據類型是隻返回自身的int32。) – Magnus

1

對於不等於具有相同散列碼的兩個對象是完全合法的,但對於具有不同散列碼的兩個對象是無效的。

字典樣式集合類使用哈希碼值(從指定爲對象的對象返回的GetHashCode值)將鍵/值對放入哈希表中。密鑰的哈希代碼值相同的所有鍵/值對都會進入同一個哈希表。如果哈希碼生成是有效的,那麼意味着字典中的每個非空哈希表中將會有非常少的(希望只有一個)鍵/值對。

當通過指定一個對象作爲鍵來訪問在字典中的內容,爲找到正確的值將被返回的僞邏輯是:

  1. 獲取哈希碼值指定爲關鍵中的對象請求(GetHashCode())
  2. 如果存在該散列碼的非空哈希表,請迭代該散列表中所有鍵/值對的關鍵對象。對於散列表中的每個鍵/值對,檢查密鑰對象Equals()是否作爲請求的關鍵字傳入的對象。如果是這樣,請返回該鍵/值對中的Value對象。

與查找List樣式集合中的對象(哈希碼分佈良好時)相比,這使得字典查找非常有效。

相關問題