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

C# 與 Java 基底類別與衍生類別建構子呼叫順序差異解析

     編輯:關於C語言

核心結論

物件導向語言中,基底類別與衍生類別的初始化順序直接影響物件狀態一致性。本文對比 C#、Java、VB.NET 三種語言的建構子執行順序,揭示關鍵差異。

測試程式碼

public class BaseClass {
    public string a = "BaseClass";
    public BaseClass() {
        a = "初始化BaseClass";
    }
}

public class ExtendClass : BaseClass {
    private string b = "ExtendClass";
    public ExtendClass() : base() {
        b = "初始化ExtendClass";
    }
}

// 使用方式
BaseClass obj = new ExtendClass();

執行順序對比表

步驟C#JavaVB.NET
1衍生類別欄位初始化(b = "ExtendClass")基底類別欄位初始化(a = "BaseClass")基底類別欄位初始化(a = "BaseClass")
2基底類別欄位初始化(a = "BaseClass")衍生類別欄位初始化(b = "ExtendClass")基底類別建構子(a = "初始化BaseClass")
3基底類別建構子(a = "初始化BaseClass")基底類別建構子(a = "初始化BaseClass")衍生類別欄位初始化(b = "ExtendClass")
4衍生類別建構子(b = "初始化ExtendClass")衍生類別建構子(b = "初始化ExtendClass")衍生類別建構子(b = "初始化ExtendClass")

深度分析

C#:衍生類別欄位優先初始化

C# 保證衍生類別的欄位初始化器在基底類別建構子執行之前完成。這意味著基底建構子執行時,衍生類別的欄位已有初始值,但衍生類別建構子本體尚未執行。這設計允許基底建構子透過虛擬方法存取衍生類別欄位(雖有風險)。

Java:基底類別優先完整初始化

Java 嚴格遵循「父類先完全初始化」原則:基底類別欄位初始化 → 基底建構子 → 衍生類別欄位初始化 → 衍生建構子。這確保基底建構子執行時,衍生類別欄位尚未初始化(仍為預設值),較安全但較不靈活。

VB.NET:基底類別欄位與建構子連續執行

VB.NET 將基底類別的欄位初始化與建構子視為不可分割的單元,先於衍生類別任何初始化完成。這介於 C# 與 Java 之間。

實務陷阱與最佳實踐

危險模式:基底建構子呼叫虛擬方法

// C# 危險範例
public class Base {
    public Base() { Initialize(); }  // 呼叫虛擬方法
    protected virtual void Initialize() { }
}

public class Derived : Base {
    private List<string> items = new List<string>();  // 欄位初始化
    protected override void Initialize() {
        items.Add("test");  // NullReferenceException!items 尚未初始化
    }
}

在 C# 中,若基底建構子呼叫被覆寫的虛擬方法,且該方法存取衍生類別欄位,將導致 NullReferenceException,因為衍生類別建構子本體尚未執行(雖欄位初始化器已跑過)。

最佳實踐建議

  • 建構子避免呼叫虛擬方法:改用非虛擬私有方法或工廠模式
  • 明確呼叫 base():雖 C# 隱含呼叫無參數基底建構子,但顯式宣告意圖更清晰
  • 欄位初始化器保持簡單:複雜邏輯移至建構子
  • 跨語言開發注意差異:移植程式碼時需驗證初始化順序假設

總結

C# 採用「衍生欄位先行」策略,Java 採用「基底完全優先」,VB.NET 採用「基底整體優先」。理解差異對編寫健壯繼承體系、避免微妙 Bug 至關重要。現代 C# 開發傾向使用工廠方法或初始化模式替代複雜建構子邏輯,從根本規避順序問題。

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