C#基类构造器调用虚方法

今天又翻出了Don Box的《Essential .Net》,又看到了当初曾经反复琢磨的虚方法分派的问题。在.net中,如果基类的构造器中调用了一个虚方法,它并不是直接调用基类中的虚方法,而是在子类中不存在override版本的时候才调用基类的虚方法,如果子类中有override版,那么就调用子类的方法。可以看个小例子,感觉下这种调用方式

public class Fruit

{

public Fruit()

{

WriteFruitName();

}

public virtual void WriteFruitName()

{

Console.WriteLine("Fruit's WriteFruitName()");

}

}

public class Banana : Fruit

{

public override void WriteFruitName()

{

Console.WriteLine("Banana's WriteFruitName()");

}

}

class Program

{

static void Main(string[] args)

{

Banana b = new Banana();

Console.ReadLine();

}

}

}

此方法执行后的结果是:Banana's WriteFruitName();因为Banana继承自Fruit,所以new Banana()首先调用基类的构造方法Fruit(),但是在基类构造方法内又调用了虚方法WriteFruitName,当程序执行到此次时,会在Banana的方法表中查找是否有方法WriteFruitName的override版,如果有则调用,没有就调用基类的虚方法。

下面看个略微深入点示例,道理都一样的,在方法中增加一名称属性,

public class Fruit

{

public Fruit()

{

FruitName = "Fruit";

WriteFruitName();

}

public virtual void WriteFruitName()

{

Console.WriteLine("Fruit's WriteFruitName(),The Name Is " + FruitName);

}

protected string FruitName{ get; set; }

}

public class Banana : Fruit

{

public Banana()

{

FruitName = "Banana";

}

public override void WriteFruitName()

{

Console.WriteLine("Banana's WriteFruitName(),The Name Is " + FruitName);

}

}

class Program

{

static void Main(string[] args)

{

Banana b = new Banana();

Console.ReadLine();

}

}

这次方法的执行结果是:Banana's WriteFruitName(),The Name Is Fruit。原因就是调用虚方法时,发现子类覆载了该方法,所以调用Banana类的WriteFruitName,但此时Banana类的构造器还没被执行,也就是说FruitName属性在Banana类中还没被赋值呢,而基类的构造器给它赋值为Fruit。这种方式仅供欣赏,实际生产中基本不这样用。