C#基礎知識整理:基礎知識(12) 超類Object

來源:互聯網
上載者:User
物件導向三大特性:封裝,繼承,多態。那麼類是從哪裡繼承呢?在物件導向語言中有基類或者也叫做超類的概念,也就是所有類都是從這個類繼承得來的,這個超類叫Object。.net中是這樣描述Object類的:
支援 .NET Framework 類階層中的所有類,並為衍生類別提供低層級服務。這是 .NET Framework 中所有類的最終基類;它是類型階層的根。
既然是超類,Object定義了一些關鍵的方法。如下:

Equals方法——用於比較兩個執行個體是否相等。
public virtual bool Equals(Object obj),比較當前執行個體是否與obj相等;
public static bool Equals(Object objA,Object objB),比較指定兩個執行個體是否相等。

Finalize 方法——允許 Object 在“記憶體回收”回收 Object 之前嘗試釋放資源並執行其他清理操作。

GetHashCode 方法——擷取一個對象的Hash值。

GetType方法——擷取當前執行個體的Type。

MemberwiseClone 方法——建立當前執行個體的淺表副本,也就是如果當前執行個體有值,新建立的執行個體中只擷取實值型別的值,參考型別是沒有擷取值。

ReferenceEquals 方法——比較兩個執行個體是否相同,與static bool Equals(Object objA,Object objB)用法一樣。

ToString 方法——這個平時用的比較多,用於返回當前執行個體的string。
Object是超類,所以C#中的所有類都具有這些方法。

下面著重介紹下Equals和ToString方法。
一、對象比較
C#中有實值型別和參考型別,簡單的理解就是實值型別儲存對象的值,而參考型別是執行個體的引用,類似於C語言的指標。因此在使用對象的比較的時候,實值型別比較兩個對象值是否相等,參考型別比較指定的引用是否引用同一個對象。當然有時也會比較參考型別指向的執行個體值是否相同。
下面是對象比較的代碼:

using System;using System.Collections.Generic;using System.Text;namespace YYS.CSharpStudy.MainConsole.AboutObject{    public class Int32Value : ICloneable    {        //欄位,定義欄位最好賦上初值        private int intValue = 0;        /// <summary>        /// 屬性        /// </summary>        public int IntValue        {            get            {                return this.intValue;            }            set            {                this.intValue = value;            }        }        /// <summary>        /// 定義一個無參構造器        /// </summary>        public Int32Value() { }        /// <summary>        /// 帶參數的構造器        /// </summary>        public Int32Value(int value)        {            this.intValue = value;        }        ///// <summary>        ///// 實現ICloneable介面        ///// </summary>        public object Clone()        {            return this.MemberwiseClone();        }    }}

調用:

using System;using YYS.CSharpStudy.MainConsole.AboutObject;namespace YYS.CSharpStudy.MainConsole{    class Program    {        static void Main(string[] args)        {            //聲明一個Int32Value類型的引用value1,指向一個執行個體            Int32Value value1 = new Int32Value(30);            //聲明value2,指向value1,此時兩個引用是指向一個執行個體的            Int32Value value2 = value1;            //使用==比較            Console.WriteLine(string.Format("value1和value2 {0}", value1 == value2 ? "相同" : "不相同"));//相同            //調用Clone,複製一個value1的副本,賦值給value2            //此時是兩個執行個體了            value2 = (Int32Value)value1.Clone();            //使用==比較            Console.WriteLine(string.Format("value1和value2 {0}", value1 == value2 ? "相同" : "不相同"));//不相同            //將value1賦給value2,此時他們指向同一個執行個體            value2 = value1;            //使用Equals比較            Console.WriteLine(string.Format("value1和value2 {0}", value1.Equals(value2) ? "相同" : "不相同"));//相同            //調用Clone,複製一個value1的副本,賦值給value2            //此時是兩個執行個體了            value2 = (Int32Value)value1.Clone();            //使用Equals比較            Console.WriteLine(string.Format("value1和value2 {0}", value1.Equals(value2) ? "相同" : "不相同"));//不相同            Console.ReadLine();        }    }}

結果:

由代碼可以看出:

a、對於參考型別,=運算子將引用從一個變數傳遞到另一個變數,所以=兩邊的變數引用同一個對象;

b、對於引用相同的兩個變數,使用==運算子返回true;

c、對象的Clone方法產生一個新執行個體,返回該執行個體的引用,該執行個體的所有欄位值和原對象相同,即Clone方法得到對象的一個副本。從Object類繼承下來的保護方法MemberwiseClone返回當前對象的副本;

d、對於Clone方法返回的對象,其引用和原對象不同,==運算子返回false;

e、從Object繼承下來的Equals方法結果和==運算子相同,只是比較當前引用(this)和參數儲存的引用是否引用到了同一個對象上。
在上述代碼的基礎上,重寫Equals方法。

using System;using System.Collections.Generic;using System.Text;namespace YYS.CSharpStudy.MainConsole.AboutObject{    public class Int32Value : ICloneable    {        //欄位,定義欄位最好賦上初值        private int intValue = 0;        /// <summary>        /// 屬性        /// </summary>        public int IntValue        {            get            {                return this.intValue;            }            set            {                this.intValue = value;            }        }        /// <summary>        /// 定義一個無參構造器        /// </summary>        public Int32Value() { }        /// <summary>        /// 帶參數的構造器        /// </summary>        public Int32Value(int value)        {            this.intValue = value;        }        ///// <summary>        ///// 實現ICloneable介面        ///// </summary>        public object Clone()        {            return this.MemberwiseClone();        }        /// <summary>        /// 覆蓋Equals方法        /// </summary>        /// <param name="obj"></param>        /// <returns></returns>        public override bool Equals(object obj)        {            bool isEquals = Object.ReferenceEquals(obj, this);            if (isEquals == false)            {                Int32Value value = obj as Int32Value;                if (value != null)                {                    isEquals = value.intValue == this.intValue;                }            }            return isEquals;        }    }}

調用

using System;using YYS.CSharpStudy.MainConsole.AboutObject;namespace YYS.CSharpStudy.MainConsole{    class Program    {        static void Main(string[] args)        {            //聲明一個Int32Value類型的引用value1,指向一個執行個體            Int32Value value1 = new Int32Value(30);            //聲明value2,指向value1,此時兩個引用是指向一個執行個體的            Int32Value value2 = value1;            //使用==比較            Console.WriteLine(string.Format("value1和value2 {0}", value1 == value2 ? "相同" : "不相同"));//相同            //調用Clone,複製一個value1的副本,賦值給value2            //此時是兩個執行個體了            value2 = (Int32Value)value1.Clone();            //使用==比較            Console.WriteLine(string.Format("value1和value2 {0}", value1 == value2 ? "相同" : "不相同"));//不相同            //將value1賦給value2,此時他們指向同一個執行個體            value2 = value1;            //使用Equals比較            Console.WriteLine(string.Format("value1和value2 {0}", value1.Equals(value2) ? "相同" : "不相同"));//相同            //調用Clone,複製一個value1的副本,賦值給value2            //此時是兩個執行個體了            value2 = (Int32Value)value1.Clone();            //使用Equals比較            Console.WriteLine(string.Format("value1和value2 {0}", value1.Equals(value2) ? "相同" : "不相同"));//相同            Console.ReadLine();        }    }}

結果:

修改後的代碼:
覆蓋了Equals方法,程式運行結果則不同了:Equals不再比較兩個變數儲存的對象引用是否相同,而是比較兩個變數所引用的對象是否具有相同的屬性值。
覆蓋後的Equals執行流程是這樣的:
我們看一下覆蓋後Equals方法的具體執行流程:

a、使用Object靜態方法ReferenceEquals比較參數obj和當前對象引用(this)是否相同,如果引用相同,則必為相同對象;
b、如果變數obj和當前引用不相同,則使用as運算子,嘗試將obj類型轉換和當前對象相同的類型,轉換成功表示obj變數引用著和當前對象類相同的對象,as運算子轉換後對象的引用,否則返回null,只有同類型的對象才需要比較,不同類型的對象必然是不同的對象;
c、如果as運算子轉換對象成功,則進一步比較當前對象引用(this)和參數obj引用對象的欄位值是否相等。
由上面兩段代碼可以看出:
==和Object類的Equals方法都是比較對象的引用是否相同,並不比較對象的欄位是否相等;而Equals方法可以覆蓋,以求讓其對對象的欄位進行等值比較或者其它的比較的需求。
因此,如果需要比較兩個C#參考型別變數,除非確定需要比較的就是對象引用時才可以使用==運算子,否則應該使用對象的Equals方法,防止對象所屬的類覆蓋了這個方法。

上面是參考型別的比較,相對來說,實值型別的比較就比較純粹。實值型別是不存在引用的,所以實值型別就是比較兩個對象值是否相等。當然如果覆蓋了Equals方法就除外了。不過一般情況下,我們無需覆蓋Equals方法。對於參考型別來說,等值比較就是比較對象的引用,引用不同的兩個對象應該就是不同的對象;對於實值型別來說,比較的就是所有欄位的值,欄位值不同的兩個對象是不同的對象。只有在特殊情況下,才需要覆蓋Equals方法,已定義某個類特殊的對象比較方法。
對於覆蓋Equals方法,要注意:
注意:理論上可以用任意代碼覆蓋Equals方法,但要保證如下原則:
a、Equals只能用於對象比較,不能做其它任何用途;
b、對於兩個已存在的對象,在對象未作任何改變的情況下,無論任何時候調用Equals方法,返回的結果應該是一樣的;
c、對於對象a和b,則a.Equalse(b)和b.Equals(a)返回的結果應該是一樣的;
d、覆蓋了Equals方法,同時要覆蓋GetHashCode(方法),這個後面再詳細說明。

二、ToString()
代碼:

   public class Int32Value : ICloneable    {        //欄位,定義欄位最好賦上初值        private int intValue = 0;        /// <summary>        /// 屬性        /// </summary>        public int IntValue        {            get            {                return this.intValue;            }            set            {                this.intValue = value;            }        }        /// <summary>        /// 定義一個無參構造器        /// </summary>        public Int32Value() { }        /// <summary>        /// 帶參數的構造器        /// </summary>        public Int32Value(int value)        {            this.intValue = value;        }        ///// <summary>        ///// 實現ICloneable介面        ///// </summary>        public object Clone()        {            return this.MemberwiseClone();        }             /// <summary>        /// 重寫ToString方法        /// </summary>        /// <returns></returns>        public override string ToString()        {            return this.intValue.ToString();            //return "重寫ToString";        }    }

調用:

     class Program    {        static void Main(string[] args)        {            Int32Value value = new Int32Value(30);            Console.WriteLine(value.ToString());//30            //Console.WriteLine(value.ToString());//重寫ToString            Console.ReadLine();        }    }

可以看出,ToString方法可以用任意代碼覆蓋,只要返回string即可,但是在覆蓋時也要返回符合需求的傳回值。

以上就是C#基礎知識整理:基礎知識(12) 超類Object 的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.