在System.Object中定義的三個比較方法有何異同

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   os   strong   2014   

分析問題

  在本書前面的章節中,筆者已經介紹過System.Object中的所有方法。而其中有三個方法被設計用來進行對象的比較,它們是:

  (1)、static bool ReferenceEquals(object A,object B)。

  (2)、static bool Equals(object A, object B)。

  (3)、virtual bool Equals(object obj)。

  1、靜態方法:ReferenceEquals實現了類型的引用比較,從參數類型可以看出,它不僅可以用來比較兩個參考型別對象,也可以用來比較兩個實值型別對象。當然,根據實值型別和參考型別的特點,ReferenceEquals方法只有應用在參考型別上時才會有意義,比較兩個實值型別的引用將永遠返回false,無論它們的值是否相等。設定於當下面的代碼被執行時:

  

int i=0;Console.WriteLine(object.ReferenceEquals(i,i));

  得到的結果將仍然是false,讀者可以嘗試從裝箱拆箱的原理去思考原因。

  2、靜態方法:Equals是另外一個靜態比較方法,它實現的功能根據不同的類型而有所不同。事實上,Equals方法的功能依靠了執行個體Equals方法的實現,概況地講,靜態Equals方法的內容分為兩步:首先檢查兩個對象是否恒等(==),然後調用其中一個參數對象的執行個體Equals方法來判斷兩個對象是否恒等。

注意

  對於實值型別和參考型別來說,檢查兩個對象是否恒等(==)的概念是不同的。對於參考型別來說,這樣的檢查是指是否引用相等,而對於實值型別來說,檢查是指標對內容進行的。

  利用發射器,可以清楚地看到靜態方法Equals的代碼:

public static bool Equals(object objA,object objB){  return ((objA==objB)||(((objA!=null)&&(objB!=null))&&(objA.Equals(objB)));}

  正如筆者前面分析的,Equals方法首先使用==運算子來檢查參數對象是否相等,然後檢查Null 參考的情況並且調用執行個體方法Equals進行比較。這樣實現的功能完全依賴於執行個體方法Equals的實現,所以讀者將不需要隱藏靜態Equals方法,而應該直接把注意力放在執行個體方法Equals上。

  3、執行個體方法:Equals實際上承擔了大部分的比較工作,它是一個虛的執行個體方法,在使用者需要構建自訂比較時,就需要從寫Equals方法。下面是mscorlib.dll的中間代碼,它展示了Object中Equals方法的預設實現:

  

  看上去十分簡單,調用了InternalEquals方法來檢查兩個對象的記憶體位址是否相等,也就是說,Equals的預設實現就是引用相等的比較。筆者在前面章節中已經介紹了,引用比較在某些場合下並不實用,而內容比較可能更加符合商務邏輯的需求,而這個時候,就需要程式員為自己的類型從寫執行個體Equals方法。事實上,所有實值型別的基類ValueType已經重寫了執行個體Equals方法。以下代碼是一個重寫的例子。

  

using System;namespace TestOverrideEquals{    class OverrideEquals    {        static void Main()        {            MyObject o1 = new MyObject(10, "我是字串");            MyObject o2 = new MyObject(10, "我是字串");            //列印引用比較結果            Console.WriteLine("引用比較:{0}", object.ReferenceEquals(o1, o2).ToString());            //列印內容比較結果            Console.WriteLine("自訂的內容比較:{0}", o1.Equals(o2).ToString());            Console.Read();        }    }    class MyObject    {        private int _MyInt;        private string _MyString;        public MyObject() { }        public MyObject(int i, string s)        {            _MyInt = i;            _MyString = s;        }        public override bool Equals(object obj)        {            //檢查Null 參考            if (obj==null)            {                return false;            }            //做引用比較,如何兩者引用相等,勢必內容相等            if (object.ReferenceEquals(this,obj))            {                return true;            }            //檢查兩者的類型是否相等            //考慮到繼承的影響,運行時的類型未必是MyObject            //所以使用反射得到確切的類型,犧牲效能來保證正確性            if (this.GetType()!=obj.GetType())            {                return false;            }            //實現內容比較            MyObject right = obj as MyObject;                        if (_MyInt==right._MyInt&&                //String類型雖然是參考型別,但實現了內容比較的==                _MyString==right._MyString)            {                return true;            }            return false;                    }    }}

  在以上代碼中,MyObject重寫了System.Object的執行個體Equals方法,實現了內容上的比較。執行程式可以得到這樣的結果:

  

注意

  以上代碼的編譯會產生一個警告,這是因為MyObject從寫了Equals方法,而沒有重寫GetHashCode方法,這樣做會產生潛在的隱患,這一點將在後續章節中有所覆蓋。

答案

  靜態方法ReferenceEquals實現了引用比較。靜態Equals方法實現了比較高效地調用執行個體Equals方法的功能。執行個體Equals方法是一個虛方法,預設的實現是參考型別,類型可以根據需要重寫執行個體Equals方法。實值型別的基類ValueType重寫了Equals方法,實現了內容的比較。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.