相信很多朋友在面對,物件判等時經常會猶豫是用“==”還是Equals呢?有時候發現兩者得到的結果相同,但有時候有不同,
究竟在什麼情況下"==" 會相等,什麼情況下Equals會不相等,看完本篇相信你心裡自有結論。
一 基本概念
值相等:表示比較的兩個物件的資料成員按記憶體位分別相等,即兩個物件型別相同,並且具有相等和相同的欄位
引用相等:表示兩個引用指向相同物件例項,也就是同一記憶體地址,(由引用相等,可以推出其值相等,反之則不能)
二 不同型別"=="與Equals 判等結果
2.1 值型別
"=="運算子:表示值是否相等
"Equals":還是表示值是否相等 ,反編譯後可以看到Equals 方法還是用了"=="運算子判等
public bool Equals(int obj) { return (this == obj); }
所以對於值型別 不管是用 "=="運算子還是Equals方法得到的結果都是一樣的(方法或運算子沒有被過載)
2.2 引用型別
2.2.1 一般引用型別的 "=="運算子:表示引用地址是否相等,
兩個物件雖然值相等,但是屬於不同例項,所有引用地址也不一樣
object a = new string(new char['a']); object b = new string(new char['a']); Console.WriteLine(a == b);//false
2.2.2一般引用型別的 Equals方法:表示值是否相等
object a = new string(new char['a']); object b = new string(new char['a']); Console.WriteLine(a.Equals(b));//true
2.2.3 特殊引用型別string: “==”運算子:表示值是否相等
string a = "123"; string b = "123"; Console.WriteLine(a==b);//true
對於為什麼string 會比較值相等,相信大家都有疑問那請看下邊的程式碼
注意:兩個stirng物件在用"=="運算子判等時會呼叫 op_Equality()方法,這個方法裡究竟做了什麼操作呢,反編譯一下string類 得到如下程式碼
我發現op_Equality()方法里居然重寫了"=="運算子 且在其中呼叫了Equals方法,那string類的Equals方法又進行了哪些操作呢,請看圖2
跟進Equals方法後發現居然是用"=="操作符判等了,瞬間我明白了大至如下:
因為string類以“==”操作符來處理值相等,
而重寫“==”操作符的方法中又呼叫了Equals方法,
而Equals方法最終還是用"=="操作符判等,
我去~~帶我們繞了個圈,最終發現string 類的 Equals方法與"=="操作符,得到結果是一樣的
//特殊引用型別string string a = "123"; string b = "123"; Console.WriteLine(a==b);//true Console.WriteLine(a.Equals(b));//true
三 自定義引用型別 “==”與 Equal判等
3.1 "=="操作符:表示引用是否相等
因為兩個例項處於託管堆中不同的塊中所引用地址必然不同,返回false
class MyClass { public string str = "123"; } MyClass myClass = new MyClass(); MyClass newClass = new MyClass(); Console.WriteLine(myClass == newClass);//false
3.2 Equals() 方法:表示相個例項是否相等
注意:為什麼會是false 明明兩個物件是一樣的啊???為什麼??為什麼??? 想知道原因?請接著看
class MyClass { public string str = "123"; } MyClass myClass = new MyClass(); MyClass newClass = new MyClass(); Console.WriteLine(myClass.Equals(newClass));//false
解釋:所有類預設都繼承了object類,Object類本身是帶有幾個方法 的,Equals就是其中之一,因為MyClass沒有過載基類Object中的 Equals虛方法所以呼叫的是Object中的Equals方法 ,那Object中的Equals方法究竟又有什麼操作呢?
反編譯一下就知道鳥
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] public virtual bool Equals(object obj) { return RuntimeHelpers.Equals(this, obj); }
RuntimeHelpers.Equals()方法官方說明:此方法判斷指定的 Object 例項是否被視為相等
很明顯 程式碼中 myClass 與 newClass 屬於不同例項,所以會返回false
若要返回True則需要過載Object中的Equals方法如下
class OverrideClass { public string Str = "123"; //過載Object中Equals方法 public override bool Equals(object obj) { OverrideClass nclass = obj as OverrideClass; //as 如果轉換失敗會返回null if (nclass == null) { return false; } //對比物件屬性是否相等 if (this.Str == nclass.Str) { return true; } else { return false; } } } OverrideClass oClass = new OverrideClass(); OverrideClass nClass = new OverrideClass(); Console.WriteLine(oClass.Equals(nClass));//true
四 總結
到這裡“==”與Equals就寫完了總結如下:
值型別:“==”操作符與Equals方法本質上沒有區別都將得到相同結果
引用型別:"=="操作符表示引用地址是否相等,Equals方法表示 值 是否相等
自定義引用型別:"=="操作符表示引用地址是否相等,Equals方法 根據過載的情況得到不同結果
特殊引用型別string:"=="與Equals 存在相互呼叫,得到結果都一樣
以上純屬個人見解,如有誤請一定指出,以免誤導
希望本文能帶給需要的朋友一點小小的收穫,如果您覺得本文對您有那麼一點點幫助還望小小的推薦一下啊,您的推薦將是我源源不斷的寫作力~