C#基礎之==(雙等於號)與equals()區別

陳大寶發表於2021-05-25

C#Equals和= =比較

這兩種方式也是大家在日常編碼工作當中用的比較多的判斷方式、之前在使用的時候也沒太關注兩者在比較不同型別的時候存在哪些區別、

今天就和大家一起深入瞭解一下其中區別

一、值型別比較判斷

對於值型別來說  兩者之間比較的都是”內容”是否相同,即值型別中的數值是否一樣,很顯然此時兩者是劃等號的,程式碼展示如下:

 #region 值型別判斷
 int i = 10;
 int j = 10;
 Console.WriteLine($"雙等於號判斷結果為:{(i == j)}");
 Console.WriteLine($"Equals判斷結果為:{i.Equals(j)}");

 #endregion

控制檯輸出:

 

 由此判斷在值型別中使用int型別為例,其中等於號與Equals二者的判斷不存在區別、都是比較其中的數值內容、那麼引用型別存在區別嗎一起來看一看?

一、引用型別比較判斷

 對於引用型別來說,等號(==)比較的是兩個變數的”引用” 是否一樣,即是引用的”地址”是否相同。而對於equals來說仍然比較的是變數的  ”內容” 是否一樣

1、引用型別中字串比較(String)

 #region 引用型別中String比較
 Console.WriteLine("----------------我是分割線-----------------------");
 string str1 = "abd";
 string str2 = "abd";
 Console.WriteLine($"雙等於號判斷結果為:{(str1 == str2)}");
 Console.WriteLine($"Equals判斷結果為:{str1.Equals(str2)}");
 #endregion

控制檯輸出:

  那麼問題來了?Equals是比較其中的數值相等返回True我可以理解、那麼字串中雙等於號是比較二者之間的引用、很顯然str1變數與str2變數是不同的引用

為什麼返回的結果怎麼還是True呢?實際的原因是什麼呢?一起來看一看

//
// 摘要:
//     Determines whether two specified strings have the same value.
//
// 引數:
//   a:
//     The first string to compare, or null.
//
//   b:
//     The second string to compare, or null.
//
// 返回結果:
//     true if the value of a is the same as the value of b; otherwise, false.
public static bool operator ==(String? a, String? b);


//
// 摘要:
//     Determines whether this instance and another specified System.String object have
//     the same value.
//
// 引數:
//   value:
//     The string to compare to this instance.
//
// 返回結果:
//     true if the value of the value parameter is the same as the value of this instance;
//     otherwise, false. If value is null, the method returns false.
public bool Equals(String? value);

不管是==、還是Equals也好都是微軟提供的public sealed class String密封類下面的提供的方法、看到此時還看不出其中的緣由、那麼直接上反編譯工具看一看究竟。

 

  點選str3==str2中的等於號繼續檢視、發現反編譯中檢視這個方法的原始碼返回了Equals這個方法、這樣一看就大致清楚了、string型別中微軟的開發

人員對這個==進行的重寫。

 

 

 

 以上是Equals與==反編譯原始碼所以這也就是當我們在比較String型別時、不同的引用、數值一樣、Equals與==返回的結果一致、相同、所以在進行String型別判斷

這兩個方法內部本質是相同的、當然String型別是一個特例。

2、引用型別中自定義型別比較

 #region 引用型別中自定義型別t比較
 Console.WriteLine("----------------我是分割線-----------------------");
 Car car1 = new Car()
 {
     Age = 4,
     Color = "Green"
 };
 Car car2 = new Car()
 {
     Age = 4,
     Color = "Green"
 };

 Console.WriteLine($"雙等於號判斷結果為:{(car1 == car2)}");
 Console.WriteLine($"Equals判斷結果為:{car1.Equals(car2)}");

控制檯輸出:

 二者都是輸出False、由於不同的引用例項、所以引用的地址也是不同的、即使數值相同==也會返回False、可能有人會產生疑問,car1 和car2的內容是相同的啊,為什麼他倆的比較結果卻是為false呢?。原因就在於在Equals是Object中的一個虛方法,而Car類中沒有對它進行重寫,因此此時呼叫的仍是父類中的Equals方法。但是父類是無法知道你都有哪些成員欄位的,因此返回的是false。要想讓他能夠比較兩個變數的內容是否相同,那就應該重寫Equals方法

2、重寫Equals並測試

新建類並測試程式碼如下:

  public class TwoDPoint : System.Object
    {
        public readonly int x, y;

        public TwoDPoint(int x, int y) 
        {
            this.x = x;
            this.y = y;
        }

        public override bool Equals(System.Object obj)
        {
            if (obj == null)
            {
                return false;
            }

            TwoDPoint p = obj as TwoDPoint;
            if ((System.Object)p == null)
            {
                return false;
            }
            return (x == p.x) && (y == p.y);
        }

        public bool Equals(TwoDPoint p)
        {
            if ((object)p == null)
            {
                return false;
            }

            return (x == p.x) && (y == p.y);
        }

        public override int GetHashCode()
        {
            return x ^ y;
        }


    }

上端呼叫測試

  #region 引用型別中自定義型別t比較
  Console.WriteLine("----------------我是分割線-----------------------");

  TwoDPoint twoDPoint1 = new TwoDPoint(4, 8);
  TwoDPoint twoDPoint2 = new TwoDPoint(4, 8);

  Console.WriteLine($"雙等於號判斷結果為:{(twoDPoint1 == twoDPoint2)}");
  Console.WriteLine($"Equals重寫後判斷結果為:{twoDPoint1.Equals(twoDPoint2)}");
  #endregion

控制檯輸出:

 

 結果顯示Equals重寫後返回True、==引用的地址不同、所以還是返回False、由此可以證明重寫後驗證成功。

總結:Equals比較的永遠是變數的內容是否相同,而= =比較的則是引用地址是否相同(前提:此種型別內部沒有對Equals 或= = 進行重寫操作,否則輸出可能會有不同)

string 型別是個特例,因為他的內部對這兩個都進行了重寫、以上本人親測有效、有什麼需要改善的歡迎大家提出來、我加以改正。有時候短短几行程式碼其實要細細研究還是會細思極恐

總而言之還是微軟的大佬的給我們封裝好了、我們拿來用就可以、但是在用的同時確實也需要有時間研究一下其中原理、其實可以多使用反編譯工具研究一下其中程式碼原理、我這裡使用的是

ILSPY

 

相關文章