引用類型的相等比較

5.3  對象的相等比較

在討論了運算符,並簡要介紹了等於運算符後,就應考慮在處理類和結構的實例時相等意味着什麼。理解對象相等比較的機制對編寫邏輯表達式非常重要,另外,對實現運算符重載和數據類型轉換也非常重要,本章的後面將討論運算符重載。

對象相等比較的機制對於引用類型(類的實例)的比較和值類型(基本數據類型,結構或枚舉的實例)的比較來說是不同的。下面分別介紹引用類型和值類型的相等比較。

5.3.1  引用類型的相等比較

System.Object的一個初看上去令人驚訝的方面是它定義了3個不同的方法,來比較對象的相等性:ReferenceEquals()和Equals()的兩個版本。再加上比較運算符==,實際上有4種進行相等比較的方式。這些方法有一些微妙的區別,下面就介紹這些方法。

1. ReferenceEquals()方法

ReferenceEquals()是一個靜態方法,測試兩個引用是否指向類的同一個實例,即兩個引用是否包含內存中的相同地址。作爲靜態方法,它不能重寫,所以只能使用System.Object的實現代碼。如果提供的兩個引用指向同一個對象實例,ReferenceEquals()總是返回true,否則就返回false。但是它認爲null等於null:

SomeClass x, y;
x = new SomeClass();
y = new SomeClass();
bool B1 = ReferenceEquals(null, null);        //return true
bool B2 = ReferenceEquals(null, x);            //return false
bool B3 = ReferenceEquals(x, y);              //return false because x and y 
                                         //point to different objects

2. 虛擬的Equals()方法

Equals()虛擬版本的System.Object實現代碼也比較引用。但因爲這個方法是虛擬的,所以可以在自己的類中重寫它,按值來比較對象。特別是如果希望類的實例用作字典中的鍵,就需要重寫這個方法,以比較值。否則,根據重寫Object.GetHashCode()的方式,包含對象的字典類要麼不工作,要麼工作的效率非常低。在重寫Equals()方法時要注意,重寫的代碼不會拋出異常。這是因爲如果拋出異常,字典類就會出問題,一些在內部調用這個方法的.NET基類也可能出問題。

3. 靜態的Equals()方法

Equals()的靜態版本與其虛擬實例版本的作用相同,其區別是靜態版本帶有兩個參數,並對它們進行相等比較。這個方法可以處理兩個對象中有一個是null的情況,因此,如果一個對象可能是null,這個方法就可以拋出異常,提供了額外的保護。靜態重載版本首先要檢查它傳送的引用是否爲null。如果它們都是null,就返回true(因爲null與null相等)。如果只有一個引用是null,就返回false。如果兩個引用都指向某個對象,它就調用Equals()的虛擬實例版本。這表示在重寫Equals()的實例版本時,其效果相當於也重寫了靜態版本。

4. 比較運算符==

最好將比較運算符看作是嚴格值比較和嚴格引用比較之間的中間選項。在大多數情況下,下面的代碼:

bool b = (x == y);          //x, y object references
表示比較引用。但是,如果把一些類看作值,其含義就會比較直觀。在這些情況下,最好重寫比較運算符,以執行值的比較。後面將討論運算符的重載,但顯然它的一個例子是System.String類,Microsoft重寫了這個運算符,比較字符串的內容,而不是它們的引用。 

發佈了17 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章