2008-12-22 115 views
2

單元測試通用字典時,我今天遇到了這個問題。System.Collections.Generic.Dictionary <T,T> .Equals實際上做了什麼?

System.Collections.Generic.Dictionary<int, string> actual, expected; 
actual = new System.Collections.Generic.Dictionary<int, string> { { 1, "foo" }, { 2, "bar" } }; 
expected = new System.Collections.Generic.Dictionary<int, string> { { 1, "foo" }, { 2, "bar" } }; 
Assert.AreEqual(expected, actual); //returns false 

失敗除了當actual == expected(對象引用是相同的)。顯然,actual.Equals(expected)也會返回false。

不錯,但是如果執行System.Collections.Generic.Dictionary<int, string>.Equals只做引用平等,那麼IEquatable有什麼意義?換句話說,爲什麼沒有經過烘焙的方式來爲泛型集合進行價值平等?

編輯感謝到目前爲止的響應。顯然我的例子是使用值類型,但我認爲我的投訴適用於所有對象。爲什麼通用集合平等不能成爲其類型平等的聯合?由於存在單獨的查找參考平等的規定,意外行爲並未真正削減它。正如康拉德魯道夫指出的那樣,我認爲這將引入僅保存實現IEquatable的對象的集合約束。然而,在像Dictionary這樣的對象中,這似乎並沒有太多要求。

回答

2

換句話說,爲什麼沒有烘焙的方式來爲泛型集合做值相等?

可能是因爲它很難在通用術語制定,因爲這隻會是可能的,如果詞典的值類型(和關鍵型)也實現IEquatable。但是,要求這樣做會太強大,使得Dictionary不適用於許多不實現此接口的類型。

這是一個約束泛型的固有問題。Haskell爲這個問題提供了一個解決方案,但是這需要一個更加強大和複雜的泛型機制。

請注意,與容器相比,IComparable的情況類似,但支持此操作,必要時使用Comparer<T>.Default

2

Dictionary<T,T>.Equals從繼承的Object.Equals並且因此確實的對象引用的簡單比較。

爲什麼泛型集合不做值相等的語義?因爲這可能不是你想要的。有時你想檢查它們是否是同一個實例。替代方案會做什麼?在每個鍵和值上調用Equals?如果這些繼承了Equals from Object?這不會是一個完整的深度比較。

所以,它給你提供一些其他的語義是否以及何時需要。

+0

另外,如果我們有一個對象字典包含自己呢?我們可能會先被程序員的小夥子殺死,但我們可能會以無限循環結束。 – configurator 2008-12-22 22:53:05

+0

另一種方法是提供一個理智,一致的平等操作語義,而不是它目前的汞合金。除非我深入瞭解繼承堆棧,否則無法告訴Equals()實際上等同於什麼! – Noel 2008-12-22 23:32:44

1

Dictionary<TKey, TValue>沒有實現IEquatable,因爲這樣有確定/知道這樣一個字典比較到另一個實際上產生相同的內容沒有正式的方式。

事實上,Dictionary<TKey, TValue>根本不會實現任何比較接口。

在我看來,有兩個對象比較自己是一件很特別的事情,所以將它放入一個接口中比將基本Object對象類中的默認通常不需要的實現放在一個接口中更有意義。它應該是一個比每個對象都能做到的東西更廣的功能,儘管不像你期望的那樣。

但是,你有它。它在那裏,你需要知道什麼時候會被使用。

就像在這種情況下一樣。

相關問題