淺析C#中的「==」和Equals的範例程式碼

黄舟
發布: 2017-03-09 15:43:55
原創
1128 人瀏覽過

  對於「==」和Equals大多數網友都是這樣總結的:

  1. “==” 是比較兩個變數的值相等。

  2. # Equals是比較兩個變數是否指向同一個物件。

  如:這篇文章,並以這篇文章中的例子為例。

public class Person
{
     public Person(string name)
     {
         this.Name = name;
     }

     public string Name { get; set; }
}

 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 g = a;
     object h = b;
     Console.WriteLine(g == h);         //false
     Console.WriteLine(g.Equals(h));    //true

     Person p1 = new Person("jia");
     Person p2 = new Person("jia");
     Console.WriteLine(p1 == p2);       //false
     Console.WriteLine(p1.Equals(p2));  //false
     Person p3 = new Person("jia");
     Person p4 = p3;
     Console.WriteLine(p3 == p4);       //true
     Console.WriteLine(p3.Equals(p4));  //true

     Console.ReadKey();
 }
登入後複製

  假如上述結論正確,「==」 是比較兩個變數值相等,那麼下面這句程式碼就不應該為True.

Console.WriteLine(a == b);         //true
登入後複製

#   很明顯,上面的兩個字串變數:a,b 是指向兩個不同的對象,即它們在堆疊空間儲存的記憶體位址也是不同的。但為毛它們就相等了呢?

 2.什麼是運算子重載?

  運算子重載,就是對現有的運算子重新進行定義,賦予其另一種功能,以適應不同的資料類型。打個簡單的比方:「+」 運算符,在「+」 兩個

  邊全為數值類型的變數時,「+」 運算子表示數學上的「+」 意義。若「+」 運算子兩邊只要有一個為字串類型,那麼「+」 運算子就表示連接

  字串的意義。這樣的運算子重載實例很多,那麼這跟本文主題有毛關係?我想說的是,上面字串變數:a , b 就是因為String類別

#   重載了運算子 “==”,看下列原始碼:

public static bool operator == (String a, String b)
{
    return String.Equals(a, b);
}
 public static bool operator != (String a, String b)
{
    return !String.Equals(a, b);
}
登入後複製

  很明顯String類別中真的重載了「==」運算符,並且不只「==」 還有 「!=」 喔。並且在重載運算子方法內部直接呼叫String類別中的Equals方法,

  原始碼如下:

public static bool Equals(String a, String b)
{
         if ((Object)a==(Object)b)
         {
             return true;
         }

         if ((Object)a==null || (Object)b==null)
         {
             return false;
         }

         if (a.Length != b.Length)
             return false;

         return EqualsHelper(a, b);
 }
登入後複製

  由上可得:「==」 運算子不一定是比較兩個變數中儲存的值是否相等,這要看目前運算子在目前這個型別中是否寫有重載。

#  3.Equals的重寫

  還是上面範例:

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
登入後複製

  由上可知:a ,b 為兩個不同的對象。但Equals為True,則上述:「Equals是比較兩個變數是否指向同一個物件「這結論不成立。原因

  看String類別中的Equals方法:

public override bool Equals(Object obj) <br>       {
    if (this == null)                        //this is necessary to guard against reverse-pinvokes and
        throw new NullReferenceException();  //other callers who do not use the callvirt instruction

    String str = obj as String;
    if (str == null)
        return false;

    if (Object.ReferenceEquals(this, obj))
        return true;

    if (this.Length != str.Length)
        return false;

    return EqualsHelper(this, str);
}

public bool Equals(String value) <br>       {
    if (this == null)                        //this is necessary to guard against reverse-pinvokes and
        throw new NullReferenceException();  //other callers who do not use the callvirt instruction

    if (value == null)
        return false;

    if (Object.ReferenceEquals(this, value))
        return true;

    if (this.Length != value.Length)
        return false;

    return EqualsHelper(this, value);
}
登入後複製

  由上面可知String類別中不僅重寫了Object中的Equals還有自己的Equals方法,但是實作程式碼幾乎是一樣的。比較類型,記憶體位址,

  實際值,從而獲得最終的結果。所以Equals不一定就是單一的比較引用位址是否相同,更何況我們還可以重寫、自訂。但是重寫

#   Equals也有需要注意的地方,就是如果你需要用到HashMap,HashSet,Hashtable那麼你也需要重寫GetHashCode()。

 4.為什麼有了「==」還要有Equals?

  中國有一句話:“任何事物的存在必然有他存在的道理和價值”,同理“==”和Equals也是一樣。 “==” 在引用型別中最基本的實作就是去比

  較兩個物件的記憶體位址是否一致,一致則相等反之則不等。這樣的實作很明顯是從硬體角度去思考的,如果兩個物件相等即為同一個對象,

  那麼它們在記憶體中的位址必然相等。 但很多時候 「行為(方法)「 是取決於我們去觀察世界的角度。  如:String類型我們申明一個字元

  串更在意的是字串所具有的實際值,而不是在意兩個物件在記憶體中是創建了一次還是兩次(即記憶體位址是否相等),只要它們所具有的

  實際值是相等的那麼我們就認為它們是相等,這是從生活業務邏輯中去理解的而不是從機器角度上去理解的。當然上面宣告相同的字串

  變數是創建一次還是兩次我想:」 常數池(或字串拘留池)「 已經給了我們最好的解決方案。

 5.「==」和Equals到底什麼關係?

    」==「 運算子和Equals它們其實是互補關係。 因為:”==“ 運算符主要實現形式是站在 ”計算機角度(或者說硬體角度)” 上去實現的,

#   而Equals是站在常用的業務場景或是特定的業務場景下去實現的,二者沒有什麼必然的聯繫,是根據自己的業務需要選擇不同方法而已。

  所以Object裡面的Equals是Visual,很多類別中都重寫了它,並且真正達了在當前類型中所需的特定行為,即:多態。所以就不難解釋上面:

object g = a;
object h = b;
Console.WriteLine(g == h);         //false
Console.WriteLine(g.Equals(h));    //true
登入後複製

  因為Object中沒有實作重載運算子:“==”,所以目前“==”的比較方式是比較兩變量在堆疊空間儲存的記憶體位址是否相同。而Equals則是

  呼叫String類別中的Equals,原因g變數在運行中它實際上指向一個字串物件的,而當前的Object類型只是Visual studio和編譯器的行為,即:還是多態。

  最後任何東西都有它的規則:」==「和Equals也不例外,詳細資料請點擊:跳轉至MSDN。


以上是淺析C#中的「==」和Equals的範例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板