C#中的ReferenceEquals、Equals以及==


    C#中有一共有四種相等性判斷方法:

//Object中定義的三個方法
public static bool ReferenceEquals(object objLeft, object objRight);
public static bool Equals(object objLeft, object objRight);
public virtual bool Equals(object obj);

//雙等號
public static bool operator == (MyClass left, MyClass right)

   

    ①Object.ReferenceEquals(left, right)靜態方法:從名稱中便可知它用來比較兩者是否是相同的引用,我們也永遠不應該去重寫該方法。它對於值類型對象的比較永遠返回false;對於兩個null的比較永遠返回true。

 

    ②Object.Equals(left, right)靜態方法:該方法也永遠不需要重寫,因為它最終會把判斷權交給參數left的實例Equls方法(代碼如下),因此沒有必要重寫該方法,只需要保證實例Equals返回想要的結果即可:

public static bool Equals(object left, object right)
{
    if(object.ReferenceEquals(left,right)) //如果引用相同,則必定相等(包含兩個都是null的情況)
    {
        return true;
    }
    if(object.ReferenceEquals(left ,null)|| object.ReferenceEquals(null,right)) //若只有一個是null,則必定不等
    {
        return false;
    }
    return left.Equals(right);//兩個都不是null,且也不是同一個引用,則根據left的實例Equals方法來判斷。
}

 

    ③Object中的實例方法Equals,因為它是虛方法,所以可以在其他類中重寫它。該方法的默認實現還是比較兩者是否為同一個引用,即相當於ReferenceEquals。但是微軟在所有值類型的基類System.ValueType中重寫了該方法,用來比較值相等。

  • 在值類型中,我們仍然可能要重寫該方法,以提高性能(默認方法的性能不高),另外如果我們的struct中包含了引用類型的成員,則應該重寫該方法。
  • 在引用類型中,如果類的實例要作為字典的鍵,則應該重寫Equals方法,使之比較值,而不是引用。

    重寫Equals應該遵循的原則:自反性、對稱性、傳遞性。即:a=a;若a=b,則b=a;若a=b,b=c,則a=c;另外兩個對象要么相等要不不等,所以該方法不應該拋出異常。下面是重寫模板:

public class MyClass:IEquatable<MyClass>
{
    //重寫Object中的Equals方法
    public override bool Equals(object obj)
    {
        if (object.ReferenceEquals(obj, null)) //首先判斷obj不能為空,否則后面對obj調用任何方法都將報錯
        {
            return false;
        }
        if(object.ReferenceEquals(this,obj)) //在C#中this永遠不會為空
        {
            return true;
        }
        if(this.GetType() != obj.GetType())
        {
            return false;
        }
        return this.Equals(obj as MyClass);
    }
    //實現IEquatable<T>中的Equals方法
    public bool Equals(MyClass other)
    {
        //省略
        return true;
    }
}

 

    ④比較運算符==:對於引用類型,默認是比較引用的(System.String除外),對於值類型默認比較值,對於自定義的結構,如果不顯示重載operator ==方法,則無法使用==。

  • 由於在C#中要求比較運算符必須成對重載,重載==運算符的同時也必須重載!=運算符,否則也會產生編譯錯誤。
  • 如果要重載的話,運算符"=="、"!="  與  Equals方法、GetHashCode方法應該同時被重載,因為他們應該保持同樣的相等邏輯。但不要再==中調用Equals,最好是在Equals中調用==。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM