新聞中心
學(xué)習(xí)C#語(yǔ)言時(shí),經(jīng)常會(huì)遇到繼承System.Object類問(wèn)題,這里將介紹繼承System.Object類問(wèn)題的解決方法。

繼承System.Object類
C#中所有的類都直接或間接繼承System.Object類,這使得C#中的類得以單根繼承。如果我們沒(méi)有明確指定繼承類,編譯器缺省認(rèn)為該類繼承System.Object類。System.Object類也可用小寫(xiě)的object關(guān)鍵字表示,兩者完全等同。自然C#中所有的類都繼承System.Object類的公共接口,剖析它們對(duì)我們理解并掌握C#中類的行為非常重要。下面是僅用接口形式表示的System.Object類:
- namespace System
- {
- public class Object
- {
- public static bool Equals(object objA,object objB){}
- public static bool ReferenceEquals(object objA,object objB){}
- public Object(){}
- public virtual bool Equals(object obj){}
- public virtual int GetHashCode(){}
- public Type GetType(){}
- public virtual string ToString(){}
- protected virtual void Finalize(){}
- protected object MemberwiseClone(){}
- }
我們先看object的兩個(gè)靜態(tài)方法Equals(object objA,object objB),ReferenceEquals(object objA,object objB)和一個(gè)實(shí)例方法Equals(object obj)。在我們闡述這兩個(gè)方法之前我們首先要清楚面向?qū)ο缶幊虄蓚€(gè)重要的相等概念:值相等和引用相等。值相等的意思是它們的數(shù)據(jù)成員按內(nèi)存位分別相等。引用相等則是指它們指向同一個(gè)內(nèi)存地址,或者說(shuō)它們的對(duì)象句柄相等。引用相等必然推出值相等。對(duì)于值類型關(guān)系等號(hào)“= =”判斷兩者是否值相等(結(jié)構(gòu)類型和枚舉類型沒(méi)有定義關(guān)系等號(hào)“= =”,我們必須自己定義)。對(duì)于引用類型關(guān)系等號(hào)“= =”判斷兩者是否引用相等。值類型在C#里通常沒(méi)有引用相等的表示,只有在非托管編程中采用取地址符“&”來(lái)間接判斷二者的地址是否相等。
靜態(tài)方法Equals(object objA,object objB)首先檢查兩個(gè)對(duì)象objA和objB是否都為null,如果是則返回true,否則進(jìn)行objA.Equals(objB)調(diào)用并返回其值。問(wèn)題歸結(jié)到實(shí)例方法Equals(object obj)。該方法缺省的實(shí)現(xiàn)其實(shí)就是{return this= =obj;}也就是判斷兩個(gè)對(duì)象是否引用相等。但我們注意到該方法是一個(gè)虛方法,C#推薦我們重寫(xiě)此方法來(lái)判斷兩個(gè)對(duì)象是否值相等。實(shí)際上Microsoft.NET框架類庫(kù)內(nèi)提供的許多類型都重寫(xiě)了該方法,如:System.String(string),System.Int32(int)等,但也有些類型并沒(méi)有重寫(xiě)該方法如:System.Array 等,我們?cè)谑褂脮r(shí)一定要注意。對(duì)于引用類型,如果沒(méi)有重寫(xiě)實(shí)例方法Equals(object obj),我們對(duì)它的調(diào)用相當(dāng)于this= =obj,即引用相等判斷。所有的值類型(隱含繼承自System.ValueType類)都重寫(xiě)了實(shí)例方法Equals(object obj)來(lái)判斷是否值相等。
注意對(duì)于對(duì)象x,x.Equals(null)返回false,這里x顯然不能為null(否則不能完成Equals()調(diào)用,系統(tǒng)拋出空引用錯(cuò)誤)。從這里我們也可看出設(shè)計(jì)靜態(tài)方法Equals(object objA,object objB)的原因了--如果兩個(gè)對(duì)象objA 和objB都可能為null,我們便只能用object. Equals(object objA,object objB)來(lái)判斷它們是否值相等了--當(dāng)然如果我們沒(méi)有改寫(xiě)實(shí)例方法Equals(object obj),我們得到的仍是引用相等的結(jié)果。我們可以實(shí)現(xiàn)接口IComparable(有關(guān)接口我們將在“第七講 接口繼承與多態(tài)”里闡述)來(lái)強(qiáng)制改寫(xiě)實(shí)例方法Equals(object obj)。
對(duì)于值類型,實(shí)例方法Equals(object obj)應(yīng)該和關(guān)系等號(hào)“= =”的返回值一致,也就是說(shuō)如果我們重寫(xiě)了實(shí)例方法Equals(object obj),我們也應(yīng)該重載或定義關(guān)系等號(hào)“= =”操作符,反之亦然。雖然值類型(繼承自System.ValueType類)都重寫(xiě)了實(shí)例方法Equals(object obj),但C#推薦我們重寫(xiě)自己的值類型的實(shí)例方法Equals(object obj),因?yàn)橄到y(tǒng)的System.ValueType類重寫(xiě)的很低效。對(duì)于引用類型我們應(yīng)該重寫(xiě)實(shí)例方法Equals(object obj)來(lái)表達(dá)值相等,一般不應(yīng)該重載關(guān)系等號(hào)“= =”操作符,因?yàn)樗娜笔≌Z(yǔ)義是判斷引用相等。
靜態(tài)方法ReferenceEquals(object objA,object objB)判斷兩個(gè)對(duì)象是否引用相等。如果兩個(gè)對(duì)象為引用類型,那么它的語(yǔ)義和沒(méi)有重載的關(guān)系等號(hào)“= =”操作符相同。如果兩個(gè)對(duì)象為值類型,那么它的返回值一定是false。
實(shí)例方法GetHashCode()為相應(yīng)的類型提供哈希(hash)碼值,應(yīng)用于哈希算法或哈希表中。需要注意的是如果我們重寫(xiě)了某類型的實(shí)例方法Equals(object obj),我們也應(yīng)該重寫(xiě)實(shí)例方法GetHashCode()--這理所應(yīng)當(dāng),兩個(gè)對(duì)象的值相等,它們的哈希碼也應(yīng)該相等。下面的代碼是對(duì)前面幾個(gè)方法的一個(gè)很好的示例:
- using System;
- struct A
- {
- public int count;
- }
- class B
- {
- public int number;
- }
- class C
- {
- public int integer=0;
- public override bool Equals(object obj)
- {
- C c=obj as C;
- if (c!=null)
- return this.integer==c.integer;
- else
- return false;
- }
- public override int GetHashCode()
- {
- return 2^integer;
- }
- }
- class Test
- {
- public static void Main()
- {
- A a1,a2;
- a1.count=10;
- a2=a1;
- //Console.Write(a1==a2);沒(méi)有定義“= =”操作符
- Console.Write(a1.Equals(a2));//True
- Console.WriteLine(object.ReferenceEquals(a1,a2));//False
- B b1=new B();
- B b2=new B();
- b1.number=10;
- b2.number=10;
- Console.Write(b1==b2);//False
- Console.Write(b1.Equals(b2));//False
- Console.WriteLine(object.ReferenceEquals(b1,b2));//False
- b2=b1;
- Console.Write(b1==b2);//True
- Console.Write(b1.Equals(b2));//True
- Console.WriteLine(object.ReferenceEquals(b1,b2));//True
- C c1=new C();
- C c2=new C();
- c1.integer=10;
- c2.integer=10;
- Console.Write(c1==c2);//False
- Console.Write(c1.Equals(c2));//True
- Console.WriteLine(object.ReferenceEquals(c1,c2));//False
- c2=c1;
- Console.Write(c1==c2);//True
- Console.Write(c1.Equals(c2));//True
- Console.WriteLine(object.ReferenceEquals(c1,c2));//True
- }
- }
【編輯推薦】
- C#窗體里調(diào)用淺談
- C#調(diào)用ListEmployee命令
- C# CreateEmployeeDefinition()函數(shù)
- C#實(shí)現(xiàn)斷點(diǎn)續(xù)傳詳細(xì)剖析
- C# Employee對(duì)象淺談
當(dāng)前名稱:繼承System.Object類概述
當(dāng)前鏈接:http://m.5511xx.com/article/ccspgsj.html


咨詢
建站咨詢
