首頁 >後端開發 >C#.Net教程 >Equals,ReferenceEquals,==的區別

Equals,ReferenceEquals,==的區別

高洛峰
高洛峰原創
2016-12-16 09:53:011074瀏覽

在.net中有幾種比較相等的方法

object的靜態ReferenceEquals()

object的靜態Equals()

object的範例Equals()

運算符==

object的範例Equals()

運算符==和用法。

ReferenceEquals

ReferenceEquals用於比較引用類型的參考是是否指向同一個物件。它只能比較引用型別。當把值類型傳給它的時候永遠都會返回false,因為值類型作為參數的時候首先會裝箱,經過裝箱的值類型哪怕是指相等,但是也是兩個不同的對象,所以變量是指向不同的對象,所以永遠回傳false。


int x = 10; 
int y = 10; 
bool b1 = object.ReferenceEquals(x,y); 

這裡結果肯定是回傳false,但如果是比較指向同一個物件,則為true。

我們還是先定義實體類別


public class Person 

private int _personId;


public int PersonId 

} { return _person }com
private string _firstName;

public string FirstName 

get { return _firstName; } 
set { _firstName = value; } 
}

private string _last; } 

}

private string _last; 

set { _lastName = value ; } 
}

public Person() { }

public Person(int personId, string firstName, string lastName) 

this._personId = personId; } 


呼叫程式碼

Person person1 = new Person(1,"Edrick","Liu"); 
Person person2 = new Person(2, "Meci", "Luo"); 
Person person3 = person; bool br1= object.ReferenceEquals(person1,person2); 
bool br2 = object.ReferenceEquals(person2, person3); 
我們可以發現第一個回傳false,第二個回傳true。那麼如果其中有一個物件為null,或是兩個物件都為null呢?結果會為false,如果兩個都為null呢?結果為true。他們不會引發異常。

實例Equals

實例Equals算是比較複雜的比較方法。實例Equals可以比較引用是否指向同一個對象,同時可以依值來比較對象。如果要按值比較對象,我們就需要重載Equals對象來實現我們的比較邏輯。同時Equals預設也支援比較值類型的相等。那我們該怎麼重載Equals來讓物件具有值相等性的比較呢?

MSDN給我們列出了一些準則

除涉及浮點型的情況外,x.Equals(x) 都回傳 true。

x.Equals(y) 傳回與 y.Equals(x) 相同的值。

如果 x 和 y 都為 NaN,則 x.Equals(y) 傳回 true。

當且僅當 x.Equals(z) 傳回 true 時,(x.Equals(y) && y.Equals(z)) 才會傳回 true。

只要不修改 x 和 y 所引用的對象,對 x.Equals(y) 的相繼呼叫將傳回相同的值。

x.Equals(nullNothingnullptrnull 引用(在 Visual Basic 中為 Nothing)) 傳回 false。

我們來看看重寫程式碼

public class Person 

private int _personId;

public int PersonId 

} { return @person }com

private string _firstName ;

public string FirstName 

get { return _firstName; } 
set { _firstName = value; } 
}

private string _last; } 

}

private string _last; 

set { _lastName = value; } 
}

public Person() { }

public Person(int personId, string firstName, string lastName) 

this._personId = personson;

}

public override bool Equals(object obj) 

if (obj != null && obj is Person) 

Person p = obj obj is Person) 

Person p = obj obj is Person) 

Person p = obj as Person; == p.FirstName) && (LastName == p.LastName); 

else 

return false; 


}

public override int GetHashCode() 

return base.GetHashCode()^PersonId;



呼叫程式碼
Person person2 = new Person(2, "Meci", "Luo"); 
Person person2 = new Person(2, "Meci", "Luo"); 
2 person3 = person;
Person person4 = new Person(1, "Edrick", "Liu");

Console.WriteLine(person4.Equals(person1)); 
Console.WriteLine(person4.Equals(person2));結果,第一個為true,第二個為false。重載的時候不能出現異常。那如果有一個類別繼承Person呢,我們又改如何比較衍生類別。

公共班級學生:人

private int _studentNumber;

public int StudentNumber 

get { return _studentNumber; 
set { 
get { return _studentNumber; 

set { 

.

public Student( int personId, string firstName, string lastName, int StudentNumber) 


this.PersonId = personId; 
this.名字= 名字; 
this.LastName = 姓氏; 
this._studenŎ NpN; Equals(object obj) 

if (obj != null && obj is Person) 

Student s = obj as Student; 
return base.Equals(obj)&&StudentNumber==s.StudentNumber; 

否則
{
回傳false; 

}

public override int GetHashCode() 

return base.GetHashCode()^StudentNumber; 

return base.GetHash Edrick", " Liu", 1); 

Student s2 = new Student(2, "Meci", "Luo", 2); 
Student s3 = new Student(1, "Edrick", "Liu", 1);

Console. WriteLine(s1.Equals(s2)); 
Console.WriteLine(s1.Equals(s3)); 
我們只需要呼叫父類別的Equals方法和衍生類別中的比較的新值。

靜態Equals

這個方法當然比較有趣的一個方法了。這個方法也是靜態的,能比較引用,能比較值型別。如果比較的型別重載了實例的Equals,那麼它也能也能比較物件的值。所以它回傳true有不同的情況。

1,引用指向同一物件

2,比較兩個null

3 ,重載了Equals的實例方法回傳true

Student s1 = new Student(1, "Edrick", "Liu", 1) ; 

Student s2 = new Student(2, "Meci", "Luo", 2); 

學生s3 = 新學生(1, "Edrick", "Liu", 1); 

學生s4 = s3;

Console .WriteLine(object.Equals(s1,s3)); 

Console.WriteLine(object.Equals(s4, s3)); 

這兩個都是true,這裡靜態的Equals跟靜態的EqualsReference有個區別,靜態的靜態的Equals如果有一個參數為null會觸發異常。


有趣下面討論一個的現象,如果重載了Equals但是沒有重載==行為,會發生什麼

Student s1 = new Student(1, "Edrick", "Liu", 1); 

學生s2 = new Student(2, "Meci", "Luo", 2); 

學生s3 = 新生(1, "Edrick", "Liu", 1); 
學生s4 = s3;

Console.WriteLine(s1= =s3); 

Console.WriteLine(s3==s4); 

第一個為假,第二個為真。這顯然不符合我們的意思,所以重載了等於必須重載==,同樣重載了==也必須重載等於。這樣符合我們的意思,也能確保在使用集合的時候,程式碼能遵循我們的意思運作。因為集合coll[0]==co[0]其實比較的是引用,但是如果我們的Equals比較的是物件的值那麼最後程式碼還是不能按照我的期望的運行。


==運算子

==號運算子其實跟實例的Equals沒有太大區別,==是運算符,而Equals是方法。它們都重寫。預設等於比較引用和比較值。關於==的重載可以參考運算子一文中的運算子重載。

總結它們的區別:

ReferenceEquals:靜態方法,不能重寫,只能比較引用,如果有參數為null返回會false,不會觸發異常,如果比較值類型,則始終傳回false。

Equals:實例方法,預設可以比較引用也可以比較值,重寫。按值比較物件。

靜態Equals:靜態方法,不能重寫。如果沒有重寫Equals,比較引用,或比較值。如果重載了Equals方法。比較引用,或者比較值,或按重寫的Equals比較,如果其中一個參數為null ,發送異常

==運算符:可以按引用比較,也可以按值比較。可以重寫。是操作運算符。

最後需要的是,如果重載了Equals,則最好是重載GetHashCode,必須重載==運算子。


更多Equals,ReferenceEquals,==的區別相關文章請關注PHP中文網!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn