嗨,我有一個具有6個字符串屬性的類。一個獨特的對象對於這些字段中的至少一個將具有不同的值C#.NET GetHashCode函數問題
要實現IEqualityComparer的GetHashCode函數,我將連接所有6個屬性並在結果字符串上調用GetHashCode。
我有以下疑點:
- 是否需要調用GetHashCode的一個獨特的價值?
- 對六個屬性的連接操作是否會使比較變慢?
- 我應該使用其他方法嗎?
嗨,我有一個具有6個字符串屬性的類。一個獨特的對象對於這些字段中的至少一個將具有不同的值C#.NET GetHashCode函數問題
要實現IEqualityComparer的GetHashCode函數,我將連接所有6個屬性並在結果字符串上調用GetHashCode。
我有以下疑點:
GetHashCode
並不需要返回的「不平等」的對象不等價。它只需要爲相等的對象返回相等的值(它也必須在對象的生命週期內返回相同的值)。
這意味着:
Equals
爲相等,那麼他們必須GetHashCode
返回相同的值。GetHashCode
實現部分。如果你不能同時滿足這兩點,那麼你應該重新評估你的設計,因爲其他任何事情都會爲漏洞開放。
最後,您可以通過在6個字符串的每一個上調用GetHashCode
,然後使用一些按位操作將所有6個結果集成一個值,使得GetHashCode
速度更快。
嗨喬恩,我的任何屬性都是隻讀的。但是,它們都有私人設置器,所以只能從構造器中進行修改。這會影響他們在GetHashCode中的使用嗎? – ganeshran
@ ganeshran:那麼它們在對象的整個生命週期內是有效的只讀(即,如果你願意,它們可以用'readonly'後臺字段來實現),這就足夠了。你會沒事的。 – Jon
@Jon讀取你的GetHashCode()實現的條件,我發現它是一個需求衝突的問題。事實上,你只是部分正確。 GetHashCode()方法的實際要求是: 1.它應該爲相等的對象返回相同的值。 2.對於同一個對象,當它沒有被修改時,它應該返回相同的值。 3. GetHashCode()應該很快。 同意,還有一些其他建議。例如這一個:爲了獲得最佳性能,散列函數應該爲所有輸入生成一個隨機分佈。 –
如果您在這些對象上調用Equals(),則GetHashCode()應該爲所有返回true的對象返回相同的哈希碼。這意味着,例如,無論字段值是什麼,您都可以返回零作爲散列碼。但是,如果存儲在哈希表等數據結構中,這會使對象非常低效。
結合弦是一種選擇,但請注意,例如,您可以結合只是stringsfor的哈希碼(同時仍然處於比較平等的所有字符串!)兩種。
您也可以結合六個單獨字符串的哈希值,而不是計算一個散列組合的字符串。看例如 Quick and Simple Hash Code Combinations
我不知道這是否會比連接字符串顯着更快。
謝謝Anders,我僅將它用於Contains方法比較。如果我只爲散列碼組合兩個字符串,如果對象中的兩個值是相同的,那麼這些散列碼是不會相同的?這會混淆比較,還是GetHashCode對比較本身沒有影響,並且只會影響性能 – ganeshran
其他人已經提出這一點,但我想用不同的方式來解決它,因爲它看起來是你的直覺卡住。注意到GetHashCode()返回一個int,它只能取得2^32個不同的值。你的對象由6個任意長度的字符串組成,顯然可以帶有大量的值。通過這個例子,我們可以很容易地看到GetHashCode()不可能是對象的所有可能值的唯一值。它只能滿足這個屬性:「if a.Equals(b)then a.GetHashCode()== b.GetHashCode()」;並注意到「如果」不能雙向進行。 –
GetHashCode()的實際考慮因素是「好」和「快」。爲了使它「快」,我會盡量避免所有的內存分配和字符串複製;使它「好」是一個細微差別的主題,但在實踐中,像@Jon所建議的那樣,將子對象的GetHashCode()值混合在一起就足夠了。我將發佈ReSharper的建議作爲「答案」,以便我可以獲取代碼格式。 –
如果字符串字段AF命名,並已知不爲空,這是ReSharper的建議,爲您的GetHashCode()
public override int GetHashCode() {
unchecked {
int result=a.GetHashCode();
result=(result*397)^b.GetHashCode();
result=(result*397)^c.GetHashCode();
result=(result*397)^d.GetHashCode();
result=(result*397)^e.GetHashCode();
result=(result*397)^f.GetHashCode();
return result;
}
}
謝謝,我將使用此代碼。 – ganeshran
在這裏看到我的答案:http://stackoverflow.com/a/34006336/1911540 –
是你計劃比較你的對象在某個地方,比如在一個數組中排序它們?這將改變是否你需要實現GetHashCode – mydogisbox
嗨mydogisbox,我用它的List.Contains方法並將比較對象傳遞給它。我已經實現了Equals,並且不知道GetHashcode的正確方法 – ganeshran