2010-04-22 18 views
2

我想在字典結構中存儲兩類的insances,並使用IEquatable來確定這些實例的唯一性。這兩個類共享一個(抽象)基類。考慮下面的類:使用IEquatable的兄弟類的C#字典唯一性<T>

abstract class Foo 
{ 
    ... 
} 

class SubFoo1 : Foo 
{ 
    ... 
} 

class SubFoo2 : Foo 
{ 
    ... 
} 

字典將delcared:Dictionary<Foo, Bar>

哪些類應被聲明爲IEquatable?對於這些聲明,通用類型T應該是什麼?這甚至有可能嗎?

回答

4

不要聲明任何內容爲IEquatable<T>。正如Marc所說,就繼承和平等而言,這通常是一個問題。

取而代之,找出這個特定字典中的鍵需要什麼樣的等式,然後執行IEqualityComparer<Foo>,然後將它傳遞給字典構造函數。

通常這是合理清楚如何比較特定情況下的密鑰。

0

這取決於你的職業所代表的。所以沒有「通用」的解決方案。如果有,那麼System.Object將執行IEquatable<object>,因爲一切都已經從object繼承。所以你可以問Object的問題,而不是Foo

長話短說,這取決於你想用你的類層次結構實現什麼。由於即使是相同的對象類型,也可能有不同的要求,但我認爲很難確定什麼使對象相等。當您使用緩存時,相等性將由對象的實體ID決定。當您使用Do-/Undo-List時,您需要使用另一個限定符,因爲該ID對於列表中的每個對象可能都是相同的。

猜猜我有點離題,但我希望我能給你一些有用的觀點。 ;-)

0

當你開始獲得繼承時,選擇一個T的確很棘手。基本類型是顯而易見的選擇,但我不知道是否更恰當地忽略EqualsGetHashCode

您可能還會得出結論:這種複雜的情況可能對密鑰的選擇不佳,而使用更簡單,更可預測的密鑰。特別是你希望「散列」基於類型的一些不變的方面,並且「散列」和「等於」必須是兼容的。如果類型不是sealed,這些細微差別很難保證。

0

您可以隨時在字典構造函數中指定自己的相等比較器。如果你不這樣做,字典會尋找IEquatable<TKey>,所以你的情況下IEquatable<Foo>因此你應該實現那個。

+0

但我personaly不喜歡IEquatable接口,並同意其他人,你應該覆蓋平等或通過你自己的比較。 – michalburger1 2010-04-22 21:27:55

0

可繼承的類應該幾乎不會執行IEquatable<T>。對於任何類型的T,實現IEquatable<T>的每個對象都應這樣做,以使得IEquatable<T>.Equals的語義將與Object.Equals的語義相匹配。如果一個類爲某些Foo實現了IEquatable<Foo>,並且派生類改變了Object.Equals的語義但未重新實現IEquatable<Foo>.Equals,後者的語義的唯一方式將與前者匹配,如果接口實現簡單地調用虛擬Object.Equals本身;如果接口只是將其參數傳遞給Object.Equals,那麼實現它就沒有好處。

相關問題