1.ReferenceEquals(object o1, object o2): 靜態方法:比較兩個對象的引用,引用相同返回true,否則返回false,同為null是返回true;ReferenceEquals進行值類型比較時總是返回false,因為兩個值類型需要分別裝箱到對象中,是不同的引用 ; ...
1.ReferenceEquals(object o1, object o2):
- 靜態方法:比較兩個對象的引用,引用相同返回true,否則返回false,同為null是返回true;ReferenceEquals進行值類型比較時總是返回false,因為兩個值類型需要分別裝箱到對象中,是不同的引用 ;
- 從名稱中便可知它用來比較兩者是否是相同的引用,我們也永遠不應該去重寫該方法。
Person zs = new Person("ZhangSan",28); Person ls = new Person("LiSi",20); Person zsCopy = zs; //ReferenceEquals比較兩個對象的引用,同為null是返回true Console.WriteLine("ReferenceEquals(zs, ls) : " + ReferenceEquals(zs, ls)); // False Console.WriteLine("ReferenceEquals(zs, zsCopy) : " + ReferenceEquals(zs, zsCopy)); //True Console.WriteLine("ReferenceEquals(ls, zsCopy) : " + ReferenceEquals(ls, zsCopy)); //Fasle Console.WriteLine("ReferenceEquals(null, null) : " + ReferenceEquals(null, null)); //True Console.WriteLine("ReferenceEquals(zs, null) : " + ReferenceEquals(zs, null)); //False Console.WriteLine("ReferenceEquals(1, 1) : " + ReferenceEquals(1, 1)); //False
2.Equals(object o):
- 虛方法:比較兩個對象的引用,由於是虛方法所以可以在自己的類中重寫它,按值來比較對象
- 重寫Equals應該遵循的原則:自反性、對稱性、傳遞性。即:a=a;若a=b,則b=a;若a=b,b=c,則a=c;另外兩個對象要麼相等要不不等,所以該方法不應該拋出異常;
Person zs = new Person("ZhangSan",28); Person ls = new Person("LiSi",20); Person zsCopy = zs; //虛擬Equals方法,比較引用,可以重寫比較值 Console.WriteLine("zs.Equals(ls) : " + zs.Equals(ls)); //Fasle Console.WriteLine("zs.Equals(zsCopy) : " + zs.Equals(zsCopy)); //True Console.WriteLine("ls.Equals(zsCopy) : " + ls.Equals(zsCopy)); //False Console.WriteLine("zs.Equals(null) : " + zs.Equals(null)); //False Console.WriteLine("1.Equals(1) : " + 1.Equals(1)); //True
3.Equals(object o1, object o2):
- 靜態方法:比較兩個對象的引用,先判斷兩個對象是否為空,如果都不為空,則調用虛擬Equals方法;
Person zs = new Person("ZhangSan",28); Person ls = new Person("LiSi",20); Person zsCopy = zs; //靜態Equals方法先比較兩個對象是否為空,如果都不為空,則調用虛擬Equals方法 Console.WriteLine("Person.Equals(zs, ls) : " + Person.Equals(zs, ls)); //False Console.WriteLine("Person.Equals(zs, zsCopy) : " + Person.Equals(zs, zsCopy)); //True Console.WriteLine("Person.Equals(ls, zsCopy) : " + Person.Equals(ls, zsCopy)); //False Console.WriteLine("Person.Equals(null, null) : " + Person.Equals(null, null)); //True Console.WriteLine("Person.Equals(zs, null) : " + Person.Equals(zs, null)); //Fasle Console.WriteLine("Person.Equals(1, 1) : " + Person.Equals(1, 1)); //True
4.object1 == object2:
- 比較運算符:可以重寫;對於引用類型,預設是比較引用的(System.String除外)來源,對於值類型預設比較值;
-
對於自定義的結構,如果不顯示重載operator方法,則無法使用。
由於在C#中要求比較運算符必須成對重載,重載==運算符的同時也必須重載!=運算符,否則也會產生編譯錯誤。
如果要重載的話,運算符"=="、"!=" 與 Equals方法、GetHashCode方法應該同時被重載,因為他們應該保持同樣的相等邏輯。但不要再==中調用Equals,最好是在Equals中調用==。
Person zs = new Person("ZhangSan",28); Person ls = new Person("LiSi",20); Person zsCopy = zs; String str1 = "Hello"; String str2 = "Hello"; String str3 = str1; //比較運算符比較引用,可以重寫 Console.WriteLine("zs == ls : " + (zs == ls)); //False Console.WriteLine("zs == zsCopy : " + (zs == zsCopy)); //True Console.WriteLine("ls == zsCopy : " + (ls == zsCopy)); //False Console.WriteLine("zs == null : " + (zs == null)); //False Console.WriteLine("1 == 1 : " + (1 == 1)); //True Console.WriteLine("str1 == str2 :" + (str1 == str2));//True Console.WriteLine("str1 == str3 :" + (str1 == str3));//True Console.WriteLine("str2 == str3 :" + (str2 == str3));//True
Equals(object o)與==的區別
- ==操作符判斷的是堆棧中的值,Equlas判斷的是堆中的值。
- C#提供值類型和引用類型:
-
- 值類型存儲在棧上,故用==判斷是直接判斷其值是否相等,因為值類型不存在堆中的數據,因此值類型的Equals也是判斷數據。即,對於值類型而言,==與Equals相同,均是判斷其值是否相等。
- 對於引用類型而言,其棧中存儲的是對象的地址,那麼==就是比較兩個地址是否相等,即是否指向同一個對象;Equals則是比較兩個對象在堆中的數據是否一樣,即兩個引用類型是否是對同一個對象的引用。
3. String類型特殊:
-
- String類型雖然是引用類型,但是對String對象的賦值卻按照值類型操作
- 對str2初始化的時候,並沒有重新開闢記憶體,而是直接將其地址指向str1的內容“hello”。這樣一來,string類型雖然是引用類型,但是其==操作和Equals操作都是一樣的,均比較值是否相等。
4. 與GetHashCode()的關係
-
- 若兩對象Equals相等,那麼其GetHashCode()必定相等;但是反過來,若GetHashCode()相等,那麼這兩個對象Equals方法比較結果不一定相同。(為了獲取最佳性能,hash函數為對象內容生成的數字是隨機分佈的,這就意味著,內容不同的對象,有可能生成的數字是一樣的,但可以認為這種概率非常小)。