詳解C# Object.Equals函數(shù)
可以說(shuō),C# Object.Equals函數(shù)完成判等操作,需要經(jīng)過(guò)三個(gè)步驟,***步是需要根據(jù)對(duì)象所屬類型的==操作符的執(zhí)行結(jié)果;第二步是判別是否為null,也是和***步一樣,需要根據(jù)類型的==操作符的執(zhí)行結(jié)果;***一步要使用到類型的Equals函數(shù)的執(zhí)行結(jié)果。也就是說(shuō)這個(gè)靜態(tài)函數(shù)的返回結(jié)果,要取決于后面要提到的兩個(gè)判等函數(shù)。類型是否提供相應(yīng)的判等函數(shù),成為這個(gè)函數(shù)返回結(jié)果的重要因素。
那么對(duì)于C# Object.Equals函數(shù)這個(gè)靜態(tài)方法來(lái)說(shuō),雖說(shuō)接受參數(shù)的類型也屬于引用類型,但是不同于Object.ReferenceEquals函數(shù),對(duì)于如下的代碼,能得出正確的結(jié)果。
- int n = 10;
- Debug.WriteLine( string.Format( "{0}", Object.Equals( n, n ) ) );
- Debug.WriteLine( string.Format( "{0}", Object.Equals( n, 10 ) ) );
這是因?yàn)樵诖撕瘮?shù)中要用到具體類型的兩個(gè)判等函數(shù),不過(guò)就函數(shù)本身而言,該做的判斷都做了,因此不需要去重載添加復(fù)雜的操作。
為了更好的述說(shuō)剩下兩個(gè)函數(shù),先解釋一下等價(jià)的意義。對(duì)于等價(jià)的意義,就是自反、對(duì)稱以及傳遞。
所謂自反,即a == a;
而對(duì)稱,是a == b,則b == a;
傳遞是 a == b,b == c,則 a == c;
理解等價(jià)的意義后,那么在實(shí)現(xiàn)類型的判等函數(shù)也要滿足這個(gè)等價(jià)規(guī)則。
對(duì)于可以重載的兩個(gè)判等函數(shù),首先來(lái)介紹的是類型的Equals函數(shù),其大致形式如下:public override bool Equals( object right );
那么對(duì)于一個(gè)類型的Equals要做些什么操作呢,一般來(lái)說(shuō)大致如下:
- public class KeyData
- {
- private int nData;
- public int Data
- {
- get{ return nData; }
- set{ nData = value; }
- } public override bool Equals( object right )
- {
- //Check null
- if( right == null )
- return false;
- //check reference equality
- if( object.ReferenceEquals( this, right ) )
- return true;
- //check type
- if( this.GetType() != right.GetType() )
- return false;
- //convert to current type
- KeyData rightrightASKeyData = right as KeyData;
- //check members value
- return this.Data == rightASKeyData.Data;
- }
- }
如上增加了一個(gè)類型檢查,即
if( this.GetType() != right.GetType() )這部分,這是由于子類對(duì)象可以通過(guò)as轉(zhuǎn)化成基類對(duì)象,從而造成不同類型對(duì)象可以進(jìn)行判等操作,違反了等價(jià)關(guān)系。
除此外對(duì)于類型的Equals函數(shù)來(lái),其實(shí)并沒(méi)有限制類型非要屬于引用類型,對(duì)于值類型也是可以重載此函數(shù),但是我并不推薦,主要是Equals函數(shù)的參數(shù)類型是不可變的,也就是說(shuō)通過(guò)此方法,值類型要經(jīng)過(guò)裝箱操作,而這是比較影響效率的。
而對(duì)于值類型來(lái)說(shuō),我推薦使用***一種判等函數(shù),即重載運(yùn)算符==函數(shù),其大致形式如下:
- public static bool operator == ( KeyData left, KeyData right );
對(duì)于一個(gè)值類型而言,其的大致形式應(yīng)該如下:
- public struct KeyData
- {
- private int nData;
- public int Data
- {
- get{ return nData;
- }
- set{ nData = value;
- }
- }
- public static bool operator == ( KeyData left, KeyData right )
- {
- return left.Data == right.Data;
- }
- public static bool operator != ( KeyData left, KeyData right )
- {
- return left.Data != right.Data;
- }
- }
由于==操作與!=操作要同步定義,所以在定義==重載函數(shù)的時(shí)候,也要定義!=重載函數(shù)。這也是。Net在判等操作保持一致性。那么對(duì)于***一個(gè)判等函數(shù),這種重載運(yùn)算符的方法并不適合引用類型。這就是。Net經(jīng)常現(xiàn)象,去判斷兩個(gè)引用類型,不要用==,而要用某個(gè)對(duì)象的Equals函數(shù)。所以在編寫自己類型的時(shí)候,要保留這種風(fēng)格。
那么對(duì)于以上介紹的四種判等函數(shù),會(huì)產(chǎn)生如下類似的對(duì)比表格。操作結(jié)果取決于 適用范圍 建議Object.ReferenceEquals 兩個(gè)參數(shù)對(duì)象是否屬于同一個(gè)引用 引用類型 不要用它來(lái)判斷值類型數(shù)據(jù)C# Object.Equals函數(shù)類型自身的判等函數(shù) 無(wú)限制 考慮裝箱操作對(duì)值類型數(shù)據(jù)產(chǎn)生的影響類型的Equals 類型重載函數(shù) 無(wú)限制考慮裝箱操作對(duì)值類型數(shù)據(jù)產(chǎn)生的影響類型的==重載 類型重載函數(shù) 無(wú)限制不要在引用類型中重載此運(yùn)算符;那么在編寫類型判等函數(shù)的時(shí)候,要注意些什么呢,給出如下幾點(diǎn)建議。
首先,要判斷當(dāng)前定義的類型是否具有判等的意義;
其次,定義類型的判等函數(shù)要滿足等價(jià)規(guī)則;
***一點(diǎn),值類型***不要重載定義Equals函數(shù),而引用類型***不要重載定義==操作符。
【編輯推薦】