從《Microsoft.net框架程序設(shè)計》一書中,看到Equals的實(shí)現(xiàn)基本分為如下三類(順序有所調(diào)整):(1)引用類型,從MyRefType到Object的繼承鏈上(基類、基類的基類、...),有類覆蓋了Object的Equals方法實(shí)現(xiàn);(2)引用類型,從MyRefType到Object的繼承鏈上(基類、基類的基類、...),均沒有類覆蓋Object的Equals方法實(shí)現(xiàn);(3)值類型的Equals方法實(shí)現(xiàn)。分法相當(dāng)科學(xué),不過我看了其中的代碼實(shí)現(xiàn),針對第二種實(shí)現(xiàn)有一些自己的疑惑和想法。為了沒有看過該書的同仁們更好地理解,我將書中的實(shí)現(xiàn)貼在此文中。先看書中第一種,(1)引用類型,從MyRefType到Object的繼承鏈上(基類、基類的基類、...),有類覆蓋了Object的Equals方法的實(shí)現(xiàn):
其中用到了Object的Equals方法,將原代碼貼出來
在這種實(shí)現(xiàn)中,個人認(rèn)為Equals方法是沒有問題的,首先調(diào)用
比較了基類的部分,然后就比較自己的部分就OK了。再看書中的第二種,2)引用類型,從MyRefType到Object的繼承鏈上(基類、基類的基類、...),均沒有類覆蓋Object的Equals方法的實(shí)現(xiàn);
我們可以發(fā)現(xiàn),同第一種實(shí)現(xiàn)的差別在于沒有了如下代碼段:
為什么不能加這一段呢?因?yàn)樵谶@種實(shí)現(xiàn)環(huán)境下,我們設(shè)定了前提:從MyRefType到Object的繼承鏈上,均沒有類覆蓋Object的Equals方法。所以如果加了上面這段代碼,那實(shí)際調(diào)用的是Object類的實(shí)例方法Equals
這樣,如果this和obj不指向同一個對象,則這個base.Equals(obj)肯定返回false,于是Equals也返回false,而在this和obj指向同一個對象,Equals返回true,這樣不就是Object的Equals()實(shí)現(xiàn)嗎?既然如此,何苦自己重新這個函數(shù)呢?既然重寫了,那肯定有不一樣的行為,于是下面的代碼段加入不得。
到這里,我們也可以理解。不過問題是,沒有加入這段代碼,從“(2)引用類型,從MyRefType到Object的繼承鏈上(基類、基類的基類、...),均沒有類覆蓋Object的Equals方法的實(shí)現(xiàn)”中,我們好像找不到比較基類成員的影子。不比較基類成員,是否合理呢?看下面例子,如果兩個Derived對象,無需比較Base部分的成員變量,那么下面的寫法是正確的,此時該程序打印出的結(jié)果為True。
但是有時邏輯要求,兩個Derived對象需要比較Base部分的成員變量,那上面的寫法就是錯誤的,此時應(yīng)該修改為如下的代碼,該程序打印出的結(jié)果為False。
再看第三種實(shí)現(xiàn):(3)值類型的Equals方法實(shí)現(xiàn)。書中代碼如下:
這種實(shí)現(xiàn)方法,如果不存在其它類對MyValType的隱式類型轉(zhuǎn)換,是沒有問題的,如果存在隱式類型轉(zhuǎn)換,那代碼中的強(qiáng)類型Equals()方法(從第16行開始)就可能存在問題了。試想想,兩種不同類型的實(shí)例,我們有多少場合會認(rèn)為他們Equals呢?根據(jù)邏輯來定,一般不會認(rèn)為它們相同。為了說明存在的這個問題,請看如下代碼:
上面代碼中,一般從常理來說,我們不會認(rèn)為myValue1和myValue2相等,因?yàn)樗麄兪遣煌愋偷膶?shí)例(myValue1屬于MyValType類型,myValue2屬于MyValType2類型)。但是實(shí)際輸出了結(jié)果True。個中原因在于定義了一個從MyValType2到MyValType的隱式轉(zhuǎn)換:
于是在運(yùn)行語句myValue1.Equals(myValue2)時,會先將myValue2轉(zhuǎn)換為一個MyValType類型的臨時變量,然后用MyValue1和這個臨時變量比較,此時調(diào)用強(qiáng)類型的比較函數(shù),因?yàn)镸yValType和MyValType2這兩個類型內(nèi)部結(jié)構(gòu)一樣,且兩變量的內(nèi)部field的值相同,所以返回True。上面例子說明 ,如果不能確保沒有其他類型到該類型的隱式轉(zhuǎn)換,那萬無一失的辦法就是不實(shí)現(xiàn)強(qiáng)類型的Equals。調(diào)用默認(rèn)的Equals方法或者實(shí)現(xiàn)參數(shù)為Object的Equals方法,雖然效率可能差一點(diǎn),但是可靠。當(dāng)然,如果可以確認(rèn)沒有其他類型到該類型的隱式轉(zhuǎn)換,那實(shí)現(xiàn)強(qiáng)類型的Equals方法還是可以帶來效率的提升。(相同描述可參見《.net框架程序設(shè)計》)。關(guān)于Equals()方法的實(shí)現(xiàn),基本上也就到此結(jié)束了。如果各位有什么好的心得,歡迎積極探討。
posted on 2009-04-26 23:33 五味雜陳 閱讀(1562) 評論(0) 編輯 收藏 引用 所屬分類: .NET
Powered by: C++博客 Copyright © 五味雜陳