淺析C# CLR的語(yǔ)言特性
本文從7個(gè)方面講述C# CLR,其中他們有new和override區(qū)別、構(gòu)造函數(shù)、abstract, virtual、as和強(qiáng)制類(lèi)型轉(zhuǎn)換等等。
1. C# CLR之new和override區(qū)別
override在子類(lèi)中重寫(xiě)基類(lèi)的方法;new在子類(lèi)中為基類(lèi)同名(virtual)方法添加一個(gè)新的版本,會(huì)保留基類(lèi)的同名(virtual)方法。
如果基類(lèi)的同名方法不給出new和override修飾符,.Net默認(rèn)采用new的方式,編譯時(shí)將產(chǎn)生一條警告信息。
關(guān)于重載:一般有按名稱(chēng)隱藏和按簽名隱藏兩種策略,C#默認(rèn)按簽名隱藏,即默認(rèn)使用hidebysig特性。
2. C# CLR之構(gòu)造函數(shù)
a) static構(gòu)造函數(shù).cctor,對(duì)類(lèi)型初始化。在類(lèi)里面聲明的靜態(tài)變量將由C#編譯器自動(dòng)編譯到.cctor中,如果有顯示的聲明靜態(tài)構(gòu)造器,也是編譯到.cctor(在.cctor中局部靜態(tài)變量將位于顯示聲明的靜態(tài)構(gòu)造器前面)。
CLR有兩種策略決定.cctor的執(zhí)行時(shí)間,第一種是首次使用類(lèi)型時(shí),第二種是首次使用類(lèi)型的靜態(tài)成員時(shí)通過(guò)給類(lèi)型添加beforefieldinit 元數(shù)據(jù)特性)。C#編譯器對(duì)沒(méi)有顯示聲明靜態(tài)構(gòu)造器的類(lèi)型默認(rèn)設(shè)置beforefieldinit特性,對(duì)存在顯示靜態(tài)構(gòu)造器的類(lèi)型不會(huì)設(shè)置。
b) 類(lèi)的構(gòu)造函數(shù).ctor。要注意的一點(diǎn)是CLR分配對(duì)象時(shí)將調(diào)用深度派生(most-derived)類(lèi)型的構(gòu)造函數(shù)方法,在派生類(lèi)型構(gòu)造函數(shù)的最開(kāi)始位置調(diào)用基類(lèi)構(gòu)造方法,不管在派生類(lèi)型本身還是基類(lèi)的構(gòu)造函數(shù)中,對(duì)象的實(shí)際類(lèi)型都是派生類(lèi)型。在這樣的機(jī)制下,有些問(wèn)題需要謹(jǐn)慎處理,例如如果基類(lèi)在構(gòu)造函數(shù)中調(diào)用被override過(guò)的virtual方法,而這時(shí)派生類(lèi)的構(gòu)造函數(shù)并沒(méi)有執(zhí)行。
3. C# CLR之a(chǎn)bstract, virtual
abstract的類(lèi)不能實(shí)例化,只能用于子類(lèi)繼承。
abstract的方法隱式的就是一個(gè)virtual方法;abstract的方法子類(lèi)必須實(shí)現(xiàn);abstract方法只能有聲明,不能包含實(shí)現(xiàn)。
virtual方法提供給子類(lèi)override;可以包含實(shí)現(xiàn)。
4. C# CLR之a(chǎn)s和強(qiáng)制類(lèi)型轉(zhuǎn)換
強(qiáng)制類(lèi)型轉(zhuǎn)換:MyClass myclass=(MyClass)obj; 使用as:MyClass myclass=obj as MyClass;
區(qū)別在于,如果obj不能被轉(zhuǎn)換成MyClass類(lèi)型,強(qiáng)制類(lèi)型轉(zhuǎn)換會(huì)拋出異常,而使用as時(shí)不會(huì)有異常,只是轉(zhuǎn)換結(jié)果(myclass變量)的值為null。
強(qiáng)制類(lèi)型轉(zhuǎn)換使用castclass操作碼(opcode)實(shí)現(xiàn),as轉(zhuǎn)換、is判斷使用isinst操作碼實(shí)現(xiàn)。這兩個(gè)操作碼都使用類(lèi)型的元數(shù)據(jù)信息,將對(duì)象轉(zhuǎn)換成給定類(lèi)型放在當(dāng)前計(jì)算堆棧上,只不過(guò)無(wú)法轉(zhuǎn)換時(shí)一個(gè)拋異常,另一個(gè)將null放在堆棧中。
關(guān)于類(lèi)型轉(zhuǎn)換:每個(gè)對(duì)象通過(guò)header中的類(lèi)型句柄引用類(lèi)型元數(shù)據(jù),在類(lèi)型元數(shù)據(jù)中有一個(gè)interface table,指示類(lèi)型實(shí)現(xiàn)了哪些接口(每個(gè)項(xiàng)都包含指向接口元數(shù)據(jù)的類(lèi)型指針),一個(gè)基類(lèi)類(lèi)型元數(shù)據(jù)指針,在接口、繼承體系之間的類(lèi)型兼容性測(cè)試主要基于這些信息進(jìn)行。類(lèi)型轉(zhuǎn)換另外需要考慮的,是類(lèi)型是否有重載隱式、顯示類(lèi)型轉(zhuǎn)換操作等。 [Page]
5. C# CLR之修飾符
private,只能在同一個(gè)類(lèi)中調(diào)用。
protected,可在派生類(lèi)中調(diào)用,無(wú)論派生類(lèi)型是否在同一個(gè)assembly中。
internal,只能在同一個(gè)assembly中調(diào)用。
protected internal,可以在任何assembly的派生類(lèi)型中調(diào)用,也可由同一個(gè)assembly中的任何類(lèi)型調(diào)用。
6. C# CLR之readonly / const區(qū)別
const在編譯之后將常量編譯到指令流中,只在元數(shù)據(jù)保留有常量名和值的信息。readonly的變量只能在聲明時(shí)提供初始化值,或者在構(gòu)造函數(shù)中初始化,之后變量的值不再允許修改。
7.C# CLR之 ref和out區(qū)別
都是表示引用方式傳遞參數(shù),out明確要求調(diào)用者進(jìn)行初始化,ref對(duì)調(diào)用方和被調(diào)用方都沒(méi)有明確的職責(zé)要求。因此對(duì)于out型的參數(shù),如果在調(diào)用之前沒(méi)有初始化賦值,會(huì)產(chǎn)生一個(gè)編譯器錯(cuò)誤。
以上就是對(duì)C# CLR的簡(jiǎn)單介紹。
【編輯推薦】