C# 中==與Equals方法比較
先來段程式碼,如下:
static void Main(string[] args) { string a = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); Console.WriteLine(a == b); //True Console.WriteLine(a.Equals(b)); //True object objA = (object)a; object objB = (object)b; Console.WriteLine(objA == objB); //False Console.WriteLine(objA.Equals(objB)); //True Person p1 = new Person("user"); Person p2 = new Person("user"); Console.WriteLine(p1 == p2); //False Console.WriteLine(p1.Equals(p2)); //False Person p3 = new Person("user"); Person p4 = p3; Console.WriteLine(p3 == p4); //True Console.WriteLine(p3.Equals(p4)); //True Console.Read(); }
答案是
true
,
true
,
false
,
true
,
false
,
false
,
true
,
true
。
為什麼會出現這個答案呢?
因為值型別是儲存在記憶體中的堆疊(以後簡稱棧),而引用型別的變數在棧中僅僅是儲存引用型別變數的地址,而其本身則儲存在堆中。
總結如下:
1. 對於值型別,==和Equals()等價,都是比較儲存資訊的內容(即比較兩個物件的值是否相同);
2. 對於除string之外的引用型別,==比較的是棧的內容是否相同(即是否指向同一個堆中地址),Equals()判斷是否對同一個物件的引用(即堆中的內容是否相同);
3. string是一種特殊的引用型別,在C#語言中,過載了Object物件的很多方法(包括equals()方法),使
string
物件用起來就像是值型別一樣
下圖為string類中過載的Equals方法描述:
4. 對於一些自定義類,我們看看是否有過載Equals方法,如果沒有則預設為基類的Equals方法(如果基類沒有過載Equals方法則為Object類Equals方法),Object類中Equals方法比較也是棧中的地址,而不是堆中的內容。
下圖為Object類中Equals方法描述:
因此我們不難理解下面的結果:
Person p1 = new Person("user");
Person p2 = new Person("user");
Console.WriteLine(p1 == p2); //False
Console.WriteLine(p1.Equals(p2)); //False
5. 對於string型別有必要強調一下
string a = "hello";
string b = "hello";
object objA = (object)a;
object objB = (object)b;
Console.WriteLine(objA == objB); //True
Console.WriteLine(objA.Equals(objB)); //True
結果:True,True
這是因為系統並沒有給字串b分配記憶體,只是將"hello"
指向了b。所以a和b指向的是同一個字串(字串在這種賦值的情況下做了記憶體的優化)。