在C#中若是存在類的繼承關係,應避免在構造函數中調用虛函數。這是因爲C#的運行機制形成的,緣由以下:ide
新建一個類實例時,C#會先初始化該類(對類變量賦值,並將函數記在函數表中),而後再初始化父類。構造函數的執行則相反,先執行父類的,再執行自己的。函數
若是類包含對父類虛函數的重載,在父類構造函數中調用虛函數時,會執行函數表中繼承類的虛函數,這就有問題了。測試
下面是個測試例子:spa
public class Base { public Base() { System.Console.WriteLine("Base.Base"); ABitDangerousCall(); } public virtual void ABitDangerousCall() { System.Console.WriteLine("Base.ABitDangerousCall"); } private class Inner { public Inner() { System.Console.WriteLine("Base.Inner.Inner"); } } private Inner inner = new Inner(); } class Derived : Base { public Derived() { System.Console.WriteLine("Derived.Derived"); ctorInitializedMember = 5; } // ctorInitializedMember is default initialized to zero before the constructor initializes it. private int ctorInitializedMember; private int derivedInt = 6; public override void ABitDangerousCall() { System.Console.WriteLine(String.Format("Derived.ABitDangerousCallctorInitializedMember={0} derivedInt={1}", ctorInitializedMember, derivedInt)); } private class Inner { public Inner() { System.Console.WriteLine("Derived.Inner.Inner"); } } private Inner inner = new Inner(); } class Program { static void Main(string[] args) { Derived d = new Derived(); Console.Read(); } }
若是真有在構造函數中調用虛函數的必要,應將該類或該重載的虛函數設爲seal,以免被繼承。code