首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 物件初始化順序完整解析:靜態/實例、基類/派生類、欄位/建構函式

     編輯:關於C#

掌握 C# 物件初始化順序對避免微妙 Bug 至關重要。本文透過完整範例程式與輸出追蹤,詳細闡述八個階段的執行序列,並揭露「基類建構函式呼叫虛擬方法」的經典陷阱與兩階段建構解法。

初始化八階段順序

  1. 派生類靜態欄位
  2. 派生類靜態建構函式
  3. 派生類實例欄位
  4. 基類靜態欄位
  5. 基類靜態建構函式
  6. 基類實例欄位
  7. 基類實例建構函式
  8. 派生類實例建構函式

驗證範例程式


class Base {
    static Base() { Console.WriteLine("Base.Static.Constructor"); }
    public Base() {
        Console.WriteLine("Base.Instance.Constructor");
        m_Field3 = new Tracker("Base.Instance.Field3");
        Virtual(); // 危險:呼叫虛擬方法
    }
    private Tracker m_Field1 = new Tracker("Base.Instance.Field1");
    private Tracker m_Field2 = new Tracker("Base.Instance.Field2");
    private Tracker m_Field3;
    static private Tracker s_Field1 = new Tracker("Base.Static.Field1");
    static private Tracker s_Field2 = new Tracker("Base.Static.Field2");
    public virtual void Virtual() { Console.WriteLine("Base.Instance.Virtual"); }
}

class Derived : Base {
    static Derived() { Console.WriteLine("Derived.Static.Constructor"); }
    public Derived() {
        Console.WriteLine("Derived.Instance.Constructor");
        m_Field3 = new Tracker("Derived.Instance.Field3");
    }
    private Tracker m_Field1 = new Tracker("Derived.Instance.Field1");
    private Tracker m_Field2 = new Tracker("Derived.Instance.Field2");
    private Tracker m_Field3;
    static private Tracker s_Field1 = new Tracker("Derived.Static.Field1");
    static private Tracker s_Field2 = new Tracker("Derived.Static.Field2");
    public override void Virtual() { Console.WriteLine("Derived.Instance.Virtual"); }
}

class Tracker { public Tracker(string text) { Console.WriteLine(text); } }

實際輸出追蹤


Derived.Static.Field1
Derived.Static.Field2
Derived.Static.Constructor
Derived.Instance.Field1
Derived.Instance.Field2
Base.Static.Field1
Base.Static.Field2
Base.Static.Constructor
Base.Instance.Field1
Base.Instance.Field2
Base.Instance.Constructor
Base.Instance.Field3
Derived.Instance.Virtual   ← 派生類虛擬方法在基類建構函式中被呼叫!
Derived.Instance.Constructor
Derived.Instance.Field3

關鍵觀察與規則

  • 欄位先於建構函式:實例欄位初始化器在建構函式本體前執行。
  • 靜態先於實例:類別首次被存取時執行靜態初始化。
  • 派生類靜態/欄位先於基類:但實例建構函式相反(基類先執行)。
  • 欄位依宣告順序初始化,但不應依賴此順序。

經典陷阱:基類建構函式呼叫虛擬方法

輸出顯示 Derived.Instance.Virtual 在 Base.Instance.Constructor 期間執行,此時派生類建構函式尚未執行,Derived.m_Field3 仍為 null。若虛擬方法存取該欄位將導致 NullReferenceException。

解法:兩階段建構


Derived d = new Derived(); // 階段一:完成物件建構
d.Virtual();               // 階段二:安全呼叫虛擬方法

最佳實踐清單

  1. 避免在建構函式中呼叫虛擬方法。
  2. 若需初始化時執行多型邏輯,採用兩階段建構或工廠模式。
  3. 靜態建構函式保持簡單,避免循環相依。
  4. 不要依賴欄位初始化順序撰寫相依邏輯。

深入理解初始化順序,是寫出健壯 C# 程式碼的基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved