最近,在基類的構造函數中調用虛方法時,發現了一個問題。先把問題重現如下:
class Program{static void Main(string[] args){var c = new Chinese(18);Console.ReadKey();}}public class People{public int Age { get; protected set; }protected People(){this.Say();}public virtual void Say(){Console.WriteLine(string.Format("基類說我今年{0}歲了", Age));}}public class Chinese : People{public Chinese(int age){this.Age = age;}public override void Say(){Console.WriteLine(string.Format("子類說我今年{0}歲了",Age));}}
運行以上的代碼,結果會是以下兩種情況之一嗎?
基類說我今年18歲了
子類說我今年18歲了
都不是!而是:
為什麼?
→調用子類構造函數new Chinese(18)
→先調用父類無參構造函數,並調用虛方法Say
→發現虛方法Say
有重載,就調用子類Chinese
中Say
的重載,但此時子類Chinese
還沒有對Age
屬性初始化,此時的Age
屬性值為默認值0
如何避免呢?
--去掉在基類構造函數中調用虛方法的代碼
--用子類實例調用重載方法
class Program{static void Main(string[] args){var c = new Chinese(18);c.Say();Console.ReadKey();}}public class People{public int Age { get; protected set; }protected People(){}public virtual void Say(){Console.WriteLine(string.Format("基類說我今年{0}歲了", Age));}}public class Chinese : People{public Chinese(int age){this.Age = age;}public override void Say(){Console.WriteLine(string.Format("子類說我今年{0}歲了",Age));}}
總結:當在基類構造函數中調用虛方法需謹慎,因為當父類調用虛方法重載的時候,子類還沒有被初始化,可能會涉及到一些成員還未被初始化。