讓你徹底理解 “==”與 Equals

Zery發表於2013-09-05

  相信很多朋友在面對,物件判等時經常會猶豫是用“==”還是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 存在相互呼叫,得到結果都一樣

 

 

以上純屬個人見解,如有誤請一定指出,以免誤導

希望本文能帶給需要的朋友一點小小的收穫,如果您覺得本文對您有那麼一點點幫助還望小小的推薦一下啊,您的推薦將是我源源不斷的寫作力~

 

 

相關文章