2009-10-30 76 views
9

我有一個字典,我正在比較另一個字典(變量類型爲IDictionary)。做d1.Equals(d2)產生錯誤。寫下我自己的代碼產生真實。兩者都是System.Collections.Generic.Dictionary。我是否缺少一些東西,或者Dictionary沒有一個Equals實現比較鍵/值?Dictionary.Equals()是否有一個實現?

private static bool DictEquals<K, V>(IDictionary<K, V> d1, IDictionary<K, V> d2) 
{ 
    if (d1.Count != d2.Count) 
     return false; 

    foreach (KeyValuePair<K, V> pair in d1) 
    { 
     if (!d2.ContainsKey(pair.Key)) 
      return false; 

     if (!Equals(d2[pair.Key], pair.Value)) 
      return false; 
    } 

    return true; 
} 

回答

10

Dictionary.Equals()使用來自Object的默認Equals,檢查兩個對象是否與所有其他默認集合相同。你可以自由地創建你自己的具有值語義的子類,儘管這通常也包括不可變的東西。

+2

+1,正如它在Dictionary類文檔中所述。 http://msdn.microsoft.com/en-us/library/3eayzh46.aspx。 – 2009-10-30 14:12:48

5

也許Dictionary類的Equals方法簡單地訴諸默認實現從繼承Object,也就是說,它只是比較有自己的引用傳遞的Dictionary對象引用。請參閱:Object.Equals reference

1

其他人所說的,它使用的Object.Equals實現,可以使用以下方法來覆蓋它:

public class EqualsDictionary<T, T> : Dictionary<T, T> 
{ 
    public override bool Equals(object obj) 
    { 
     //Place your comparison implementation here 
    } 
} 
+2

要*覆蓋它,就像關鍵字說的那樣。重載是不同的。 – Joren 2009-10-30 14:16:45

+0

@Joren:是的,對我來說還爲時過早。 – 2009-10-30 14:25:56

2

假設兩本字典,一個是SortedList<TKey, TValue>和一個Dictionary<TKey, TValue>,針對比較平等,如果項目是相同的,它是否真的返回true?這將是非常糟糕的,因爲它們具有不同的特徵和功能(例如SortedList<,>允許通過索引進行檢索)。

此外,相等和散列碼在邏輯上連在一起。散列碼應該是不可變的,否則所有基於散列的算法將不起作用。當您使用內容檢查平等時,您無法保證這一點。因此,默認實現(檢查它們是否是相同的實例)是相當理智的。您可以自由創建自己的內容平等比較。

+0

公平點,我上面的代碼應該比較內容之前進行通常的身份+班級比較檢查。 – 2009-10-30 14:24:53

+0

對。然而,由於散列碼的問題,這仍然不適合替換Equals():如果兩個對象相等,則它們的散列碼必須相等,並且散列碼必須是不可變的。結果,Equals()可能不會僅僅因爲兩個集合具有相同內容的相同類型而返回true,因爲它們仍然會有不同的(不可變的,難以強調的)哈希碼。 – Lucero 2009-11-01 23:57:28

+0

@Lucero:這太糟糕了。NET只定義了一組虛擬等價關係方法,因爲大多數「不可變」的類類型持有對可能會變的對象的引用,除了引用永遠不會暴露給可能會改變它們的任何東西*並且如果有的話是那些不可變包裝類可以用來對其內容進行哈希或校驗相等的標準方法。 – supercat 2013-11-03 20:46:25

0

除了封裝對象狀態的不可變方面之外,.NET中的引用可用於封裝對象的身份,其狀態的可變方面,兩者或兩者都不包含。一般來說,如果沒有特殊的理由,.NET會假定引用可變對象用於封裝標識。它進一步假設,在代碼比較引用而不知道它們代表什麼的情況下,最好在報告事情不一致方面犯錯。因此,對可變對象的兩個引用通常被認爲是等價的,當且僅當它們識別相同的對象時,可變類型因此不鼓勵覆蓋Equals以指示其他任何內容。相反,使用引用來封裝可變狀態的代碼應該使用除Object.Equals()以外的其他方法來比較它們。

相關問題