程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#基礎知識 >> C#掃盲之:==/Equals /ReferenceEquals 異同的總結,相等性你真的知道嗎?

C#掃盲之:==/Equals /ReferenceEquals 異同的總結,相等性你真的知道嗎?

編輯:C#基礎知識

1.前言

== Equals ReferenceEquals 三個相等性測試,是.NET提供給程序員使用的三個方法,他們之間有什麼聯系和區別,你真的仔細研究過?雖然之前也多多少少知道一點,但是有時候又難免混淆他們之間的概念和所適用的場合,決定做一個總結系統的描述這三個寶寶

2.值類型比較和引用類型比較

在編程中實際上我們只需要這兩種比較,c#中類型也就這兩種

  (1)值類型的比較:一般我們就是判斷兩個值類型實例的各自包含的值是否相等

  (2)引用類型的比較:由於引用類型在內存中的分布有兩部分,一個是引用類型的引用(存在於線程棧中),一個是引用類型的值(存在於托管堆);所以我們比較引用類型也就存在兩種比較

默認情況下:值類型比較的是兩個值是否相等(不裝箱情況下),引用類型比較的是兩個引用是否相等。

3.==, Equals,ReferenceEquals 的闡述

        3.1==

   定義:靜態相等符號,對應存在的!=,這個符號是一個可以重載的二元操作符,可以用於比較兩個對象是否相等。使用==比較對象時,C#在編譯時就決定了所比較的類型,而且不會執行任何虛方法(Object.Equals)。這是大家所期望的相等行比較。

  • 對於內置值類型,==判斷的是兩個對象的代數值是否相等。它會根據需要自動進行必要的類型轉換,並根據兩個對象的值是否相等返回true或者false
  • 對於引用類型,則==一般情況下比較的這是引用類型的引用是否相等。

  注意:但是某些內置的引用類型重載了==符號,例如string就重載==,使其比較的不是兩個字符串的引用,而是比較的兩個字符串字面量是否相等,如下圖,所以對於引用類型最好不要使用==符號進行相等性比較,避免混淆。【對於引用類型利用==除了string是比較其值外,其余都是比較其引用,因為string是經常需要操作,所以會直接比較其值,所以會對其特殊對待,所以如果遇見特殊的引用類型需要查看一下是否進行了==重載,默認情況大家都可以把==在比較引用類型時當成比較引用!

  

  值類型的==比較:雖然i和j在棧上具有不同的內存空間,但是他們的代數值都為5;m和n類型被自動轉換並比較代數值

int i = 5;
int j = 5;
 Console.WriteLine(i == j);//值類型比較代數值 輸出True

 int m = 6;
 double n = 6.0;
 Console.WriteLine(m == n);//類型自動轉換並比較數值 輸出True
==值類型比較

  引用類型==比較:如下代碼,兩個object對象都在堆上申請了空間,在線程棧上存在兩個不同的引用,所以輸出結果為False

object obj1 = new object();
object obj2 = new object();
Console.WriteLine(obj2==obj1);//引用類型比較引用 輸出False
==引用類型比較

  3.2 Equals

  定義:Equals屬於Object的實例方法,用於比較兩個對象的引用是否相等,注意:對於Object對象比較的是引用!

     然而對於值類型,類型相同(不會進行類型自動轉換),並且數值相同(對於struct的每個成員都必須相同),則Equals返回 true,否則返回false。這是為什麼呢?                 這是因為內置的值類型都重寫了Object.Equals方法,所以值類型的Equals方法與引用類型的Equals就產生了不同的效果。

      Equals在程序運行時決定比較的類型--根據對象的實際類型進行比較,根據對象的類型調用他們各自的Equals虛方法。

            int i = 5;
            int j = 5;
            Console.WriteLine(i.Equals(j));//值類型比較 輸出True

            int m = 6;
            double n = 6.0;
            Console.WriteLine(m.Equals(n));//類型不會自動轉換並比較數值 輸出False

            object obj1 = new object();
            object obj2 = new object();
            Console.WriteLine(obj2.Equals(obj1));//引用類型比較 輸出False
            Console.WriteLine(obj2.Equals(string.Empty));//輸出False,比較量對象的類型不同直接返回False        
Equals比較

  3.3 ReferenceEquals 

  定義:Object的靜態方法,比較兩對象的引用是否相等,值類型和引用類型都是一樣。

            int i = 5;
            int j = 5;
            Console.WriteLine(object.ReferenceEquals(i, j));//輸出False

            int m = 6;
            double n = 6.0;
            Console.WriteLine(object.ReferenceEquals(m, n));//輸出False

            object obj1 = new object();
            object obj2 = new object();
            Console.WriteLine(object.ReferenceEquals(obj1, obj2));//輸出False
ReferenceEquals比較

4.三種比較方法的相同和區別

通過以上的探討我們知道

ReferenceEquals比較對象的引用是否相同,而且是安全的比較
==和Equals異同

相同點: 對於值類型 都是比較代數值是否相等
不同點:(1)對於值類型比較,==會進行類型的自動轉換,然後比較代數值,Equals則不會進行轉換,先比較類型,再比較值,如果類型不同直接返回false
      (2)==比較是安全的比較,也就是說兩對象為任何值都可以進行比較,不會拋出異常;而Equals的比較則是不安全的,由於在Equals在運行時才會進行真正的比較,有可能調用Equals的調用者是NULL,編譯通過,但是運行時則會拋出異常

所以對於引用類型是要使用實例的Equals進行比較時,一定不要忘記檢查調用者對象是否為空。而Object提供的靜態Equals方法也是安全的不需要檢查,下面的方法等效於Object提供的靜態Equals方法

 public static bool AreEqual(object obj1, object obj2)
 {
    if (obj1 == null)
        return obj2 == null;
    return obj1.Equals(obj2);
 }
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved