class Base
{
static Base() { Console.WriteLine("Static Base"); }
public Base() { Console.WriteLine("Base"); }
}
問題:`new Base()` 輸出什麼?
錯誤直覺:只輸出 "Base" (以為靜態建構函數不會被觸發)。
正確輸出:
Static Base Base
規則 (依據 ECMA-334 / MSDN):
class Child : Base
{
static Child() { Console.WriteLine("Static Child"); }
public Child() { Console.WriteLine("Child"); }
}
`new Child()` 輸出:
Static Child Static Base Base Child
順序口訣:子類靜態 → 父類靜態 → 父類實例 → 子類實例 (與實例建構函數順序相反)。
abstract class A
{
public A() { PrintFields(); }
public virtual void PrintFields() { }
}
class B : A
{
int x = 1;
int y;
public B() { y = -1; }
public override void PrintFields() => Console.WriteLine($"x={x}, y={y}");
}
問題:`new B()` 輸出什麼?
常見誤區:抽象類別不能實例化,所以不能有建構函數 / 編譯錯誤。
事實:抽象類別可以且通常應定義建構函數**,供衍生類別呼叫初始化基底狀態。
執行流程:
x=1, y=0 (y 為預設值 0)「靜態建構函數由 CLR 在類別首次被使用前自動觸發,繼承鏈中子類靜態建構函數優於父類。抽象類別擁有建構函數供衍生類別鏈式初始化,但在建構函數中呼叫虛擬方法會導致衍生類別欄位未初始化即被使用,屬於危險模式,應避免。」