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

1.前言

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

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

在編程中實際上咱們只須要這兩種比較,c#中類型也就這兩種程序員

  (1)值類型的比較:通常咱們就是判斷兩個值類型實例的各自包含的值是否相等編程

  (2)引用類型的比較:因爲引用類型在內存中的分佈有兩部分,一個是引用類型的引用(存在於線程棧中),一個是引用類型的值(存在於託管堆);因此咱們比較引用類型也就存在兩種比較c#

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

3.==, Equals,ReferenceEquals 的闡述

        3.1==

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

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

  注意:可是某些內置的引用類型重載了==符號,例如string就重載==,使其比較的不是兩個字符串的引用,而是比較的兩個字符串字面量是否相等,以下圖,因此對於引用類型最好不要使用==符號進行相等性比較,避免混淆。【對於引用類型利用==除了string是比較其值外,其他都是比較其引用,由於string是常常須要操做,因此會直接比較其值,因此會對其特殊對待,因此若是碰見特殊的引用類型須要查看一下是否進行了==重載,默認狀況你們均可以把==在比較引用類型時當成比較引用!測試

  

  值類型的==比較:雖然i和j在棧上具備不一樣的內存空間,可是他們的代數值都爲5;m和n類型被自動轉換並比較代數值spa

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 Equals3d

  定義: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);
 }
因爲本人才學識淺,描述不免紕漏,若有錯誤,歡迎指出。麼麼!

參考資料:
http://www.cnblogs.com/yang_sy/p/3582946.html
http://www.cnblogs.com/zagelover/articles/2741409.html
相關文章
相關標籤/搜索