避免在构造函数中调用虚方法(Do not call overridable methods in constructors)
Posted 蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了避免在构造函数中调用虚方法(Do not call overridable methods in constructors)相关的知识,希望对你有一定的参考价值。
CLR中说道,不要在构造函数中调用虚方法,原因是假如被实例化的类型重写了虚方法,就会执行派生类型对虚方法的实现。但在这个时候,尚未完成对继承层次结构中所有字段的初始化。所以,调用虚方法会导致不可预测的行为。归根结底,这是由于调虚方法时,直到运行时之前,都不会选择执行该方法的实际类型。
在MSDN中,也给我我们详细的提示和范例。
https://msdn.microsoft.com/en-us/library/ms182331.aspx
那我们就亲手来测试一下,新建两个类,Perople类,Chinese类,先不要看结果,看到下面这两个类,想想在实例化Chinese的时候,会是什么输出结果呢?
1 public class People
2 {
3 public People()
4 {
5 PeopleSayHello();
6 }
7
8 public virtual void PeopleSayHello()
9 {
10 Console.WriteLine("hello");
11 }
12 }
public class Chinese : People
{
private bool HaveAbility { get; set; }
public Chinese()
{
HaveAbility = true;
}
public override void PeopleSayHello()
{
Console.WriteLine((HaveAbility?"有":"没有")+"能力说你好");
}
}
接下来来看调用和输出结果吧:
是不是和你在脑海里运行的结果相同?
其实原因在第一句话中已经说的比较清晰了,更通俗的说就是在派生类实例化的时候,如果没有显式调用基的任意一个构造函数,那么默认选择基类的无参构造。所以在本例中,实例化Chinese的时候,首先执行了基类的无参构造。
和实例构造器初始化的顺序也相关,在创建实例的时候,首先为数据字段分配内存,然后初始化对象附加字段,包括类型对象的指针引用,最后才调用类型的构造函数设置对象的初始状态。
以上是关于避免在构造函数中调用虚方法(Do not call overridable methods in constructors)的主要内容,如果未能解决你的问题,请参考以下文章