2009-09-10 70 views
12

我已經使用Dictionary(TKey,TValue)用於很多目的。但是我沒有遇到任何實現GetHashCode()的場景,我相信這是因爲我的鍵是像int和string這樣的主類型的。 我很好奇,想知道的情況下(現實世界的例子)時,應該使用自定義對象的關鍵,從而實現方法的GetHashCode()等於()等我們何時爲字典執行GetHashCode()?

,並使用自定義對象的關鍵必要實施這些不功能?

+0

可能的重複[爲什麼在重寫Equals方法時重寫GetHashCode非常重要?](http://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when- equals-method-is-overridden) – nawfal 2013-04-14 11:48:51

回答

13

只要默認Object.Equals(測試引用相等)不足,您應該覆蓋EqualsGetHashCode。例如,如果您的密鑰類型是自定義類型,並且您希望兩個密鑰即使在它們不是自定義類型的同一實例的情況下也是相同的,則會發生這種情況。

例如,如果你的關鍵很簡單,只要

class Point { 
    public int X { get; set; } 
    public int Y { get; set; } 
} 

,你想要兩個Point的兩個被認爲是相等的,如果他們的X s爲平等的,他們的Y s爲相等的,那麼你就需要重寫EqualsGetHashCode

+0

關於字典,等於和GetHashCode需要是什麼,如果1)我編輯對象的位置和交換'point.X'爲'point.Y'?該值是否必須刪除,並重新添加到字典中? – LamonteCristo 2012-10-16 21:24:14

2

一個例子是當你需要創建一個組合鍵(這是一個由多個數據組成的鍵)。該組合鍵將是需要覆蓋這些方法的自定義類型。

例如,假設您有一個地址記錄的內存緩存,並且您想檢查一個地址是否在緩存中以節省昂貴的行程以檢索數據庫。我們還可以說,地址在他們的街道1郵政編碼字段中是唯一的。你會像這樣的東西實現緩存:

class AddressCacheKey 
{ 
    public String StreetOne { get; set; } 
    public String ZipCode { get; set; } 

    // overrides for Equals and GetHashCode 
} 

static Dictionary<AddressCacheKey,Address> cache; 

由於您AddressCacheKey型覆蓋EqualsGetHashCode方法,他們將在辭典的鍵,一個很好的候選人,你會能夠確定您是否需要訪問數據庫以基於多個數據檢索記錄。

1

這裏有兩個問題。

  1. 當你需要實現 的GetHashCode()
  2. 你曾經使用對象的辭典鍵。

讓我們先從1.如果你正在寫的是有可能會被別人使用的類,你將要定義的GetHashCode()和equals(),在參考值等於()是不夠的。如果你不打算在字典中使用它,並且這是爲了你自己的用法,那麼我看不到有任何理由跳過GetHashCode()等。

對於2),你應該在任何需要時使用對象從一個對象到另一個類型有一個恆定的時間查找。由於GetHashCode()返回一個數字值,並且集合存儲引用,因此通過Int或字符串使用Object(記住一個字符串是一個對象)不會有任何損失。

9

只是要清楚:有一件重要的事情有關Dictionary<TKey, TValue>GetHashCode():字典使用的GetHashCode確定兩個密鑰是相同的,即如果<TKey>是你應該關心認真落實GetHashCode()自定義類型。正如Andrew Hare指出的那樣,這很容易,如果你有一個簡單的類型來明確地標識你的自定義對象。如果你有一個組合的標識符,它會變得更復雜一點。

舉例考慮複數爲TKey。一個複數是由它的實數和虛數部分決定的。兩者都是簡單的類型,例如double。但是,如果兩個複數相等,你將如何識別?您爲自定義複雜類型實施GetHashode()並組合兩個識別部分。

您可以在後者here上找到更多信息。

UPDATE

基於Ergwun的評論我檢查的Dictionary<TKey, TValue>.Add行爲特別對於TKey的實施Equals(object)GetHashCode()。我必須承認,我對結果頗感意外。

鑑於兩個對象​​和TKeyk2,任意兩個對象v1TValuev2,和Dictionary<TKey, TValue>類型的空字典d,這是關鍵​​與關鍵詞追加v1d第一和v2時會發生什麼k2秒(取決於TKey.Equals(object)執行和TKey.GetHashCode()):

k1.Equals(k2) k1.GetHashCode() == k2.GetHashCode() d.Add(k2, v2) 
false   false         ok 
false   true         ok 
true   false         ok 
true   true         System.ArgumentException 

精讀clusion:我錯了,因爲我原本以爲第二種情況(其中Equals返回false但兩個關鍵對象具有相同的散列碼)將引發ArgumentException。但作爲第三種情況顯示字典在某種程度上使用GetHashCode()。無論如何,它似乎是一個很好的建議,兩個相同類型和相同的對象必須返回相同的哈希碼,以確保實例Dictionary<TKey, TValue>正常工作。

+9

-1 Dictionary不使用'GetHashCode()'來確定兩個鍵是否相等。也就是說,一個字典可以包含單獨的條目,其鍵具有相同的散列碼。字典可能效率較低,但它仍然有效。 – Ergwun 2011-08-16 06:17:33

+2

+1對於更新:) – Ergwun 2011-08-17 12:52:23

+0

是的,您應確保相同的對象返回相同的哈希碼(請參閱http://msdn.microsoft.com/zh-cn/library/ms182358.aspx)。 – Ergwun 2011-08-18 01:16:12

相關問題