避免在构造函数中调用虚方法(Do not call overridable methods in constructors)

CLR中说道,不要在构造函数中调用虚方法,原因是假如被实例化的类型重写了虚方法,就会执行派生类型对虚方法的实现。但在这个时候,尚未完成对继承层次结构中所有字段的初始化。所以,调用虚方法会导致不可预测的行为。归根结底,这是由于调虚方法时,直到运行时之前,都不会选择执行该方法的实际类型。

在MSDN中,也给我我们详细的提示和范例。

https://msdn.microsoft.com/en-us/library/ms182331.aspx

那我们就亲手来测试一下,新建两个类,Perople类,Chinese类,先不要看结果,看到下面这两个类,想想在实例化Chinese的时候,会是什么输出结果呢?

  public class People
{
public People()
{
PeopleSayHello();
} public virtual void PeopleSayHello()
{
Console.WriteLine("hello");
}
}
public class Chinese : People
{
private bool HaveAbility { get; set; } public Chinese()
{
HaveAbility = true;
} public override void PeopleSayHello()
{ Console.WriteLine((HaveAbility?"有":"没有")+"能力说你好");
}
}

接下来来看调用和输出结果吧:

避免在构造函数中调用虚方法(Do not call overridable methods in constructors)避免在构造函数中调用虚方法(Do not call overridable methods in constructors)

是不是和你在脑海里运行的结果相同?

其实原因在第一句话中已经说的比较清晰了,更通俗的说就是在派生类实例化的时候,如果没有显式调用基的任意一个构造函数,那么默认选择基类的无参构造。所以在本例中,实例化Chinese的时候,首先执行了基类的无参构造。

和实例构造器初始化的顺序也相关,在创建实例的时候,首先为数据字段分配内存,然后初始化对象附加字段,包括类型对象的指针引用,最后才调用类型的构造函数设置对象的初始状态。

上一篇:LARGE_INTEGER


下一篇:【总结整理】js获取css的属性(内部,外部,内嵌(写在tag中))