2012-06-06 69 views
7

我有一個覆蓋GetHashCode()的CustomObject對象。 我有一個HashSet,我可以用兩個具有相同散列碼的不同對象調用add。 這兩個都得到了補充,後來我終於遇到了一些數據庫插入問題(主鍵重複項)...使用hashSet的目的連接到了這些數據庫插入項(避免了關鍵衝突)。爲什麼C#hashSet接受添加具有相同getHashCode()值的兩個對象?

我可能錯過了一些HashSet的屬性?即使我在添加(.Add)之前嘗試檢查(.Contains),我最終會添加hashCode重複項...

+2

如果哈希碰撞足以讓HashSet考慮兩個值重複,那麼這將是非常沒有價值的。預計不同值的相同散列值。 – delnan

+0

那麼,完美的哈希是一個有意義的概念 – Jerome

回答

22

因爲HashSet<T>成員資格基於對象相等性,而不是哈希碼相等。根據Equals,只要成員不同,對HashSet<T>的每個成員都具有相同的哈希碼是完全合法的。散列碼在HashSet<T>中扮演的角色是快速測試成員資格。如果您有一個對象,並且其散列碼不在HashSet<T>中,那麼您知道該對象不在HashSet<T>中。如果您有一個對象,並且其散列代碼位於HashSet<T>中,那麼您必須使用相同的散列代碼測試相同的對象鏈,使用Equals來檢查該對象是否實際位於HashSet<T>之內。這就是爲什麼平衡散列碼分佈很重要。但情況並非如此,唯一的散列碼是必要的。

+0

這是錯誤的說哈希集是基於相等的,因爲它基於相等和散列碼。首先計算散列來選擇一個精確的地址,然後使用等於將元素放置在衝突列表中。 –

+3

您正在討論實現細節。 HashSet是一個集合,成員資格由Equals平等決定。恰巧它使用散列碼來提高性能。閱讀我的答案,我已經指出了你描述的機制。請刪除downvote。 – jason

1

不是使用哈希集嘗試避免重複的值。使用它們來平衡哈希表!

+0

這並不回答爲什麼允許重複散列的問題。 –

+0

咦?集合是過濾出重複項的不錯選擇。除非*有*沒有反映在散列和平等之間的差異,並且關心哪個對象被保留,但是這似乎相當罕見。我對.NET世界瞭解不多,也許我錯過了什麼? – delnan

+0

@ChrisShain,delnan我說實話,我以爲我已經添加了這個作爲評論,只是注意到。 – asawyer

8

覆蓋GetHashCode是不夠的。您還需要重寫Equals函數。

+0

這是爲什麼被拒絕? – GianT971

+1

爲什麼這是低調?也許不是*完整*答案,但肯定是一個開始點。所以我用+1進行了調整。 –

相關問題