2011-11-12 11 views
0

GetHashCode的方法可靠性我試圖哈希並保持(散列),其具有約1000個條目IEnumerable<anotherobject>類型的object。我將生成另一個這樣的對象,但這次我想使用這兩個對象的哈希代碼來檢查條目值的任何更改。在Silverlight/WP7.1

基本上,我想知道如果GetHashCode()易於此,無論從性能的角度和可靠性的角度。

如果我必須重寫它,那麼這樣做的好方法是什麼,它總是取決於anotherobject的類型以及當比較兩個anotherobject時意味着什麼Equals?有沒有一種通用的方法來做到這一點?這個擔心是因爲我的對象可能很大。

回答

2

GetHashCode的返回值被保證是用於僅在應用程序的執行相同的相同對象的相同;如果您在應用程序執行之間存儲散列碼,則不能保證可靠。有關更多信息,請參閱MSDN文檔System.Object.GetHashCode()(「如果應用程序再次運行,可以通過[GetHashCode]返回不同的哈希碼。」)。事實上,截至2016年3月,現在已經記錄了不同進程和不同應用程序域(甚至在同一進程內)之間可能存在差異的哈希代碼,請參閱GetHashCode文檔中的警告框。

絕對不應該使用GetHashCode的返回值來確定對象的相等性。調用Equals也是必要的。

有關實現GetHashCode的指導,請參閱文檔的繼承者說明。

上的GetHashCode的默認實現:

GetHashCode方法的默認實現不執行對不同的對象不 保證唯一的返回值。此外,.NET Framework不保證 GetHashCode方法的默認實現,並且它返回的值將在 不同版本的.NET Framework之間相同。因此,不得將此方法的默認實現用作散列目的的唯一對象 標識符。

(請注意,這是不同的,例如,Java的默認實現hashCode(),這是記錄在案,以嘗試返回不同的對象不同的值「儘可能合理實用」。)

如果您需要更穩定的散列函數,因此,您必須使用自己的散列函數,更重要的是,記錄散列函數以確保其穩定性並確保用戶可以依賴其穩定性。

這裏有幾種選擇,如MurmurHash3,MD5等。這裏最重要的是記錄你正在使用的哈希函數。

+0

謝謝,那麼,我的選擇是什麼? – abhinav

+0

我的意思是,我該如何生成可靠的哈希碼?閱讀完編輯之後,我發現我根本不應該使用'GetHashCode()'。那麼,你回答了這個問題,但。謝謝!無論如何,如果您有任何關於哈希代碼生成的建議,我將不勝感激。 – abhinav

+0

我編輯了我的答案。 –

2

得到不同的價值觀爲同一對象的值不同對象的價值觀和相同的價值觀 ,總是

這事沒有散列函數可以給你。你正在將一個龐大的(最有可能是無限的)宇宙投射到四十億個價值中。肯定會碰撞。

當然,它取決於類型 - 如果您的類型數值有限(例如,由兩個16位座標組成的點),您可能會遇到無碰撞的GetHashCode。但字符串,雙打或更復雜的類型?編號

哈希函數的標準(渴望)屬性是,它們不能給你錯誤的否定匹配,但它們可以給你錯誤的肯定匹配(這也是根源於.Net的文檔,所以任何GetHashCode預計表現如此)。

所以標準的工作流程是:

  1. 比較兩個對象的哈希值。如果爲false,則對象不相等。
  2. 否則做完全平等測試。

請參閱GetHashCode的文檔。

編輯:

注意,默認實現相當多回報一些內部的.Net實例ID,所以絕對不適合幾乎任何東西。你應該認識到,從System.Object的角度來看,只有兩個對象是相同的實例,兩個對象纔是相同的。

基於價值的平等是必須由程序員定義的語義。

默認實現返回該對象的索引由公共語言運行時確定 。該索引對於執行引擎的實例的AppDomain內的對象的實例是唯一的。 但是,由於該指數可以垃圾收集期間 回收對象後可重複使用,也能夠獲得相同的 哈希代碼兩個不同的對象。此外,代表 相同值的兩個對象只有在它們完全相同的 對象時才具有相同的哈希碼。這個實現對散列並不特別有用;因此,派生類應該重寫GetHashCode。

See this.

+0

謝謝,我會編輯這個問題。那麼,默認(繼承)'GetHashCode()'夠好嗎? – abhinav

+0

@abhinav編輯 –

+0

+1,謝謝,您的編輯告訴我'爲什麼'我不應該使用'GetHashCode()',我可以從這種方法繼續而不是找到解決方法。 – abhinav