區別和認識四個判等函式

2021-04-09 07:18:16 字數 3836 閱讀 6690

**:愚翁

(李建忠blog)

.net

有四個判等函式?不少人看到這個標題,會對此感到懷疑。事實上確是如此,

.net

提供了referenceequals

、靜態equals

,具體型別的

equals

以及==

操作符這四個判等函式。但是這四個函式之間有細微的關係,改變其中乙個函式的實現會影響到其他函式的操作結果。

首先要說的是

object.referenceequals

和object.equals

這兩個靜態函式,對於它們倆來說,是不需要進行重寫的,因為它們已經完成它們所要得做的操作。

對於object.referenceequals

這個靜態函式,函式形勢如下:

public static bool referenceequals( object left, object right );

這個函式就是判斷兩個引用型別物件是否指向同乙個位址。有此說明後,就確定了它的使用範圍,即只能對於引用型別操作。那麼對於任何值型別資料操作,即使是與自身的判別,都會返回

false

。這主要因為在呼叫此函式的時候,值型別資料要進行裝箱操作,也就是對於如下的形式來說。

int n = 10;

object.referenceequals( n, n );

這是因為對於

n這個資料裝箱兩次,而每次裝箱後的位址有不同,而造成

object.referenceequals( n, n )

的結果永遠為

false

。對於第乙個判等函式來說,沒有什麼好擴充套件的,因為本身已經很好地完成了它所要做的。

對於第二個

object.equals

這個靜態函式,其形式如下:

public static bool equals( object left, object right );

按照書中對它的分析,其大致函式**如下:

public

static

void equals( object left, object right )

可以說,

object.equals

這個函式完成判等操作,需要經過三個步驟,第一步是需要根據物件所屬型別的

==操作符的執行結果;第二步是判別是否為

null

,也是和第一步一樣,需要根據型別的

==操作符的執行結果;最後一步要使用到型別的

equals

函式的執行結果。也就是說這個靜態函式的返回結果,要取決於後面要提到的兩個判等函式。型別是否提供相應的判等函式,成為這個函式返回結果的重要因素。

那麼對於

object.equals

這個靜態方法來說,雖說接受引數的型別也屬於引用型別,但是不同於

object.referenceequals

函式,對於如下的**,能得出正確的結果。

int n = 10;

debug.writeline( string.format( "", object.equals( n, n ) ) );

debug.writeline( string.format( "", object.equals( n, 10 ) ) );

這是因為在此函式中要用到具體型別的兩個判等函式,不過就函式本身而言,該做的判斷都做了,因此不需要去過載新增複雜的操作。

為了更好的述說剩下兩個函式,先解釋一下等價的意義。對於等價的意義,就是自反、對稱以及傳遞。

所謂自反,即

a == a

;而對稱,是

a == b

,則b == a

;傳遞是

a == b

,b == c

,則a == c

;理解等價的意義後,那麼在實現型別的判等函式也要滿足這個等價規則。

對於可以過載的兩個判等函式,首先來介紹的是型別的

equals

函式,其大致形式如下:

public override bool equals( object right );

那麼對於乙個型別的

equals

要做些什麼操作呢,一般來說大致如下:

public

class keydata

set }

public

override

bool equals( object right )

}

如上增加了乙個型別檢查,即

if( this.gettype() != right.gettype() )

這部分,這是由於子類物件可以通過

as轉化成基類物件,從而造成不同型別物件可以進行判等操作,違反了等價關係。

除此外對於型別的

equals

函式來,其實並沒有限制型別非要屬於引用型別,對於值型別也是可以過載此函式,但是我並不推薦,主要是

equals

函式的引數型別是不可變的,也就是說通過此方法,值型別要經過裝箱操作,而這是比較影響效率的。

而對於值型別來說,我推薦使用最後一種判等函式,即過載運算子

==函式,其大致形式如下:

public static bool operator == ( keydata left,keydata right );

對於乙個值型別而言,其的大致形式應該如下:

public

struct keydata

set }

public

static

bool

operator == ( keydata left,keydata right )

public

static

bool

operator != ( keydata left, keydata right )

}

由於

==操作與

!=操作要同步定義,所以在定義

==過載函式的時候,也要定義

!=過載函式。這也是

.net

在判等操作保持一致性。那麼對於最後乙個判等函式,這種過載運算子的方法並不適合引用型別。這就是

.net

經常現象,去判斷兩個引用型別,不要用

==,而要用某個物件的

equals

函式。所以在編寫自己型別的時候,要保留這種風格。

那麼對於以上介紹的四種判等函式,會產生如下類似的對比**。

操作結果取決於

適用範圍

建議object.referenceequals

兩個引數物件是否屬於同乙個引用

引用型別

不要用它來判斷值型別資料

object.equals

引數型別自身的判等函式

無限制

考慮裝箱操作對值型別資料產生的影響

型別的equals

型別過載函式

無限制

考慮裝箱操作對值型別資料產生的影響

型別的==過載

型別過載函式

無限制

不要在引用型別中過載此運算子

那麼在編寫型別判等函式的時候,要注意些什麼呢,給出如下幾點建議。

首先,要判斷當前定義的型別是否具有判等的意義;

其次,定義型別的判等函式要滿足等價規則;

最後一點,值型別最好不要過載定義

equals

函式,而引用型別最好不要過載定義

==操作符。  

《Effective C 》 區別四個判等函式

net有四個判等函式?不少人看到這個標題,會對此感到懷疑。事實上確是如此,net提供了referenceequals 靜態equals,具體型別的equals以及 操作符這四個判等函式。但是這四個函式之間有細微的關係,改變其中乙個函式的實現會影響到其他函式的操作結果。首先要說的是object.ref...

認識事物的四個階段

size medium 我們的工作生活中總是有各種事物需要認識,規律需要掌握。工作中對哲學的思考是否有幫助呢?答曰 有幫助。但不可以過度追求和捨本逐末,正如先知指向天空說這是月亮,而我們不可以誤解其手指是月亮 而如果是真正智慧型的先知也會先點撥手指和指示是什麼。階段一 看山是山 看水是水 最淺層認識...

認識UWB的四個誤區

誤區一 uwb只能短距離執行 這種理解是不正確的。雖然uwb在技術上是一種短程無線技術 如藍芽 wifi和nfc 但這實際上更像是乙個類別列表。uwb的工作頻率介於6.5ghz和10ghz之間,而藍芽的固定頻率為2.4ghz。一般規律是頻率越高,距離越短。然而,在條件允許下,uwb的工作範圍可以延伸...