程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 淺析C#中的“==”和Equals,

淺析C#中的“==”和Equals,

編輯:C#入門知識

淺析C#中的“==”和Equals,


1.“==”和Equals兩個真的有關聯嗎?

         對於“==”和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) 
{ 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)
{ 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。

 

          

         

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved