熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

C#中的類型相等與恆等(Equality & Identity)

2013-11-13 12:21:22  來源: .NET編程 

  CLR提供了可以區分類型的Equality 和Identity能力

  Equality

  
如果兩個對象是相同的類型並且它們各自帶有相同和等值的屬性

  Equality必須滿足三個必要條件reflexive symmetrics and transitive

  reflexive: 自身相等及a==a 是永遠成立的

  symmetrics: 對象性及a==b成立那麼b==a 也成立

  transitive: 傳遞性及a==b b==c成立那麼a==c 也成立

  Identity

  
兩個對象必須相等(意味著他們共享同一塊內存區域)

  CLR提供了至少四種方法來判斷兩個對象的等價性

  Public static bool ReferenceEquals(object left object right);

  Public static bool Equals(object left object right);

  Public virtual bool Equals(object right);

  Public static bool operator==(MyClass left MyClass right); 

  ReferenceEquals方法總是用來判斷兩個對象的Identity的不管是針對值類型還是引用類型所以針對值類型調用該方法總是會返回false因為值類型作為這個方法的參數時會進行裝箱操作

  靜態的Equals方法提供了判斷兩個對象的Equality能力在其實現的內部調用了上述第三個虛擬的Equals方法和ReferenceEquals一樣它們已經具備從底層判斷兩個對象的能力我們從來不會覆寫這兩個方法

  實例Equals方法也是用來區分兩個對象的Equality的

  對於引用類型的對象它和ReferenceEquals方法幾乎是一樣的(因為判斷兩個引用類型是否的Equality往往從Identity上就可以區分)

  而值類型的對象我們不僅要判斷他們具有相同的對象類型還要判斷他們的值相等值類型從SystemValueType繼承而來ValueType已經重寫了ObjectEquals()方法本來已經可以用來滿足這些要求的但是ValueTypeEquals()方法不是很有效因為它必須要通過反射在不知道具體的派生類型中完成對它們所含有成員變量的值的比較因此建議在我們實現一個值類型的數據結構時同時重寫ValueTypeEquals()方法

  然而我們再回頭看看引用類型有時兩個引用類型的對象往往被用來進行類似值類型的比較比如String類型它雖然是引用類型但它也重寫了Equals方法因為我們拿它來判斷兩個string是否相同(Equality)實際是希望判斷它們是否具有相同的內容這是一個value semantics因此我們建議在考慮實現一個用作值語義環境下的引用類型時候也重寫基類的ObjectEquals()方法

  注請參考MDSN或其它相關文檔如何實現Equals方法的重寫

  上面的圖示給了很好的例子來區分Equals和ReferenceEquals方法被用來做Equility和Identity判斷的區別

  ==運算符是可由類重載的運算符它也是用來判斷恆等的

  對於未重載==的引用類型會比較兩個引用類型是否引用同一個對象這跟引用類型的Equals()方法是一樣的

  對於未重載==的值類型該運算符會比較這兩個值是否按位相等即是否這兩個值中的每個字段都相等和Equals方法一樣推薦在自定義值類型中也要重載==運算符因為也存在反射在效率上的影響

  ==運算符和Equals方法的區別在於多態表現上Equals方法是重寫而==運算符是被重載這意味著除非編譯器知道調用具體的重載版本否則它只是調用未重載的==版本


From:http://tw.wingwit.com/Article/program/net/201311/15731.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.