CLR via C 常量,欄位和方法

2021-10-04 12:45:59 字數 4779 閱讀 5347

常量:具有以下特性:

1.c#允許定義基元型別常量,也允許定義非基元型別常量(值必須為null)。

2.常量被視為靜態成員(不能用static修飾),而不是例項成員。

3.常量的指向和值都不允許被修改。

字段:具有以下特性:

1.c#允許定義任何資料型別的字段。常用的字段修飾符如下表所示:

clr術語

c#術語

說明static

static

instance

預設欄位是例項的一部分,而不是型別的一部分。當構造型別的例項時,就會為該字段分配動態記憶體。

initonly

readonly

欄位的指向不能被修改(可以通過反射進行修改),但是欄位的值可以被修改。一般在定義時初始化,也可以在建構函式裡面初始化。

volatile

volatile

不對字段做執行緒不安全優化措施

方法:具有以下特性:

1.il中使用返回型別+方法名稱+引數列表來唯一標識乙個方法;其他程式語言(c#)中使用方法名稱+引數列表來唯一標識乙個方法。

2.clr中提供了兩種命令來呼叫方法,分別如下所示:

1>.call命令用來呼叫靜態方法,例項方法和虛方法。當call呼叫靜態方法時,必須指定方法的型別;當call呼叫例項方法和虛方法時,必須指定引用物件的變數。

2>.callvirt只能用來呼叫例項方法和虛方法,且必須檢查指定的引用物件的變數是否為null,如果為null就會丟擲異常,所以call的執行效率要高於callvirt。

3.使用new修飾方法時,表明該方法是類中的新方法,跟基類中同名的方法沒有任何關係。

4.引用型別例項建構函式具有以下特性:這裡的字段指的是例項欄位而不是靜態字段。

1>.例項建構函式是不能被繼承的,所以不能用sealed,abstract,virtual,override,new來修飾該函式。

2>.如果類的修飾符為static(即是sealed和abstract)或者重寫了例項建構函式時,編譯器就不會生成預設的例項建構函式;否則編譯器就會生成預設的例項建構函式。

3>.當編譯器生成預設的例項建構函式時,如果類的修飾符為abstract的話,預設例項建構函式的可訪問性為protected;否則可訪問性為public。

4>.當基類有提供無參例項建構函式(編譯器預設生成或者程式設計師自己重寫)時,當派生類沒有顯示呼叫乙個基類例項建構函式時,編譯器預設呼叫無參例項建構函式,否則就呼叫指定的例項建構函式;當基類沒有提供無參例項建構函式時,派生類必須顯示呼叫乙個基類例項建構函式,否則編譯報錯。

5>.當尚未完成繼承層次中所有欄位的初始化時,不要在例項建構函式中呼叫虛函式,否則會造成無法預知的後果。

6>.建立物件的流程如下:

1>>.為物件分配記憶體空間。

2>>.將所有沒有顯示初始化的字段設定成null或者0。

3>>.初始化型別物件指標和同步塊索引。

4>>.呼叫例項建構函式來初始化字段。流程如下所示:

1>>>.初始化類定義中顯示設值的字段。

2>>>.呼叫基類的例項建構函式來初始化基類中的字段。

3>>>.初始化例項建構函式中顯示設值的字段。

4>>>.我們最好不要定義欄位時初始化,而是放在預設例項建構函式中初始化。其他例項構造函式呼叫預設例項建構函式來完成初始化工作並且對指定的字段按照指定的引數來修改初始化值。

5.值型別例項建構函式具有以下特性:這裡的字段指的是例項欄位而不是靜態字段。

1>.編譯器不僅不預設生成例項構造器,而且也不允許程式設計師定義無參例項建構函式,但是其他支援clr的語言,如il組合語言是允許程式設計師定義無參例項建構函式。

2>.編譯器預設不呼叫例項建構函式,除非使用new關鍵字來顯示呼叫。當new顯示呼叫無參例項建構函式時,編譯器不報錯且字段會初始化為null或者0。

3>.編譯器不允許欄位在定義時進行顯示初始化。

4>.當定義了例項建構函式時,就必須對所有的字段進行初始化。

7.操作符過載函式具有以下特性:可以參考decimal類相關實現。

1>.clr要求操作符過載函式必須是public static,且至少有乙個引數的型別跟定義該操作符過載函式的型別相同。

2>.c#要求使用"operator加上操作符"來過載操作符函式;然後編譯器會生成具有specialname標記的"op_*特殊方法名"的il指令;最後建議提供乙個友好的相容與cls的方法名供外界呼叫。

其中允許過載的一元操作符如下表所示:

c#操作符

特殊方法名

相容與cls方法名

+op_unaryplus

plus

-op_unarynegation

negate

!op_logicalnot

not~

op_onescomplement

onescomplement

++op_increment

increment

–op_decrement

decrement

無op_true

istrue

無op_false

isfalse

其中允許過載的二元操作符如下表所示:

c#操作符

特殊方法名

相容與cls方法名

+op_addition

addition

-op_subtraction

subtract

*op_multiply

multiply

/op_division

division

%op_modulus

mod&

op_bitwiseand

bitwiseand

op_bitwiseor

^op_exclusiveor

xor<<

op_leftshift

leftshift

>>

op_rightshift

rightshift

==op_equality

equals

!=op_inequality

equals

<

op_lessthan

compare

>

op_greaterthan

compare

<=

op_lessthanorequal

compare

>=

op_greaterthanorequal

compare

3>.核心fcl型別(int32,int64,uint32等)沒有定義任何操作符過載函式,因為它們在執行操作運算時,編譯器會直接生成相關的il指令。

8.轉換操作符過載函式具有以下特性:可以參考decimal類相關實現。

1>.clr要求轉換操作符過載函式必須是public static,且引數型別和返回型別二者必須有其一跟定義該轉換操作符過載函式的型別相同。

2>.implicit表示可以顯示或者隱式呼叫轉換操作符函式;explicit表示只能顯示呼叫轉換操作符函式。所以在型別轉換時,如果不存在精度丟失以及數量級損失的話,建議用implicit;否則建議用explicit。

3>.轉換操作符過載函式的原型為:public static implicit/explicit operator 目標型別(原始型別 …)。

4>.編譯器生成的il**中轉換操作符過載函式的名字為op_implicit以及op_explicit。在il**中函式是通過函式名,引數型別和返回型別來做唯一標識。

5>.is和as永遠不會呼叫轉換操作符過載函式來做型別轉換。

6>.在做型別轉換時,除了定義轉換操作符過載函式,還需要提供建構函式和to***(指定型別)函式來做真正的型別轉換工作。

9.擴充套件函式具有以下特性:可以參考enumerable類相關實現。

1>.c#只支援擴充套件方法,不支援擴充套件事件,擴充套件屬性,擴充套件操作符等。

2>.擴充套件函式必須在非泛型的頂級靜態類(不巢狀在別的類)中定義。

3>.擴充套件函式至少要有乙個引數且第乙個引數必須使用this修飾符。

4>.擴充套件函式不會對呼叫者進行空值檢查。

5>.擴充套件函式的第乙個引數不要設定成object型別,否則所有的型別都會存在這個擴充套件函式。

6>.擴充套件函式會在該函式自身,包含該函式的靜態類以及包含該靜態類的程式集上都定製extensionattribute特性,從而方便編譯器能夠快速的查詢擴充套件函式。

7>.例項函式在呼叫時會先查詢例項型別(包含基類)中是否存在該例項函式,如果存在的話就直接呼叫例項型別中的例項函式;否則就從所有靜態類中查詢是否存在相同函式名且第乙個引數是this修飾的當前例項型別,後面引數跟例項函式傳入引數一一對應,如果是的話就找到了擴充套件函式並呼叫該擴充套件函式;否則就丟擲異常。

8>.當編譯器找到匹配的擴充套件函式大於等於兩個時,就會出現二義性異常。此時可以通過命名空間或者直接使用靜態類呼叫擴充套件方法的形式來解決二義性。

9>.因為版本控制原因造成被擴充套件的類提供了這個擴充套件方法的例項方法時,就會呼叫例項方法從而造成已有的程式邏輯行為未知;

10.分部函式具有以下特性:

1>.分部函式只能在分部類或分部結構內宣告。

2>.分部函式使用partial修飾,由於分部函式的實現部分可能沒有,所以分部函式的返回型別始終為void,引數型別不能有out修飾。

3>.分部函式沒有實現時,編譯器不會生成任何分部函式定義和呼叫的il**,從而提高執行時的效能。

4>.分部函式的可見性預設為private,但編譯器不允許分部函式顯示新增任何可訪問性。

5>.分部函式的宣告和實現必須具有完全一致的簽名。如果有應用定製特性的話,最終編譯器會進行合併這些定製特性。

CLR via C 讀書筆記 常量和字段

常量 constant 字段 field 欄位是一種資料成員,其中容納了乙個值型別的例項或者對乙個引用型別的引用 字段修飾符 clr術語 c 術語 說明 static static 這種欄位是型別狀態的一部分,而不是物件狀態的一部分 instance 預設 這種欄位與型別的乙個例項關聯,而不是與型別...

常量和字段

定義常量符號時,它的值必須能在編譯時確定。確定之後,編譯器將常量的值儲存到程式集的元資料中。這意味著只能為編譯器認定的基元型別定義常量。在c 中,以下型別都是基元型別,可以定義常量 boolean char byte sbyte int16 uint16 int32 uint32 int64 uin...

十八 常量和字段

常量就是定義完以後就永遠不會再改變的符號,它的值是在編譯時必須確定的,編譯通過後,編譯器將常量的值儲存在程式集的元資料中,定義常量將導致元資料的產生,常量只能是基元型別。因為常量的值不會被改變,所以可以說常量是型別的一部分,而不是例項成員的,是靜態的。當 引用乙個常量符號時,編譯器將在定義常量的程式...