1. new和override區別
override在子類中重寫基類的方法;new在子類中為基類同名(virtual)方法添加一個新的版本,會保留基類的同名(virtual)方法。
如果基類的同名方法不給出new和override修飾符,.Net預設採用new的方式,編譯時間將產生一條警告資訊。
關於重載:一般有按名稱隱藏和按簽名隱藏兩種策略,C#預設按簽名隱藏,即預設使用hidebysig特性。
2. 建構函式
a) static建構函式.cctor,對類型初始化。在類裡面聲明的靜態變數將由C#編譯器自動編譯到.cctor中,如果有顯示的聲明靜態構造器,也是編譯到.cctor(在.cctor中局部靜態變數將位於顯示聲明的靜態構造器前面)。
CLR有兩種策略決定.cctor的執行時間,第一種是首次使用類型時,第二種是首次使用類型的靜態成員時通過給類型添加beforefieldinit 中繼資料特性)。C#編譯器對沒有顯示聲明靜態構造器的類型預設設定beforefieldinit特性,對存在顯示靜態構造器的類型不會設定。
b) 類的建構函式.ctor。要注意的一點是CLR指派至時將調用深度派生(most-derived)類型的建構函式方法,在衍生類別型建構函式的最開始位置調用基類構造方法,不管在衍生類別型本身還是基類的建構函式中,對象的實際類型都是衍生類別型。在這樣的機制下,有些問題需要謹慎處理,例如如果基類在建構函式中調用被override過的virtual方法,而這時衍生類別的建構函式並沒有執行。
3. abstract, virtual
abstract的類不能執行個體化,只能用於子類繼承。
abstract的方法隱式的就是一個virtual方法;abstract的方法子類必須實現;abstract方法只能有聲明,不能包含實現。
virtual方法提供給子類override;可以包含實現。
4. as和強制類型轉換
強制類型轉換:MyClass myclass=(MyClass)obj; 使用as:MyClass myclass=obj as MyClass;
區別在於,如果obj不能被轉換成MyClass類型,強制類型轉換會拋出異常,而使用as時不會有異常,只是轉換結果(myclass變數)的值為null。
強制類型轉換使用castclass作業碼(opcode)實現,as轉換、is判斷使用isinst作業碼實現。這兩個作業碼都使用類型的中繼資料資訊,將對象轉換成給定類型放在當前計算堆棧上,只不過無法轉換時一個拋異常,另一個將null放在堆棧中。
關於類型轉換:每個對象通過header中的類型控制代碼參考型別中繼資料,在類型中繼資料中有一個interface table,指示類型實現了哪些介面(每個項都包含指向介面中繼資料的類型指標),一個基類類型中繼資料指標,在介面、繼承體系之間的類型相容性測試主要基於這些資訊進行。類型轉換另外需要考慮的,是類型是否有重載隱式、顯示類型轉換操作等。
5. 修飾符
private,只能在同一個類中調用。
protected,可在衍生類別中調用,無論衍生類別型是否在同一個assembly中。
internal,只能在同一個assembly中調用。
protected internal,可以在任何assembly的衍生類別型中調用,也可由同一個assembly中的任何類型調用。
6. readonly / const區別
const在編譯之後將常量編譯到指令流中,只在中繼資料保留有常量名和值的資訊。readonly的變數只能在聲明時提供初始化值,或者在建構函式中初始化,之後變數的值不再允許修改。
7. ref和out區別
都是表示引用方式傳遞參數,out明確要求調用者進行初始化,ref對調用方和被呼叫者都沒有明確的職責要求。因此對於out型的參數,如果在調用之前沒有初始化賦值,會產生一個編譯器錯誤。