标题比较抽象,所以我写了一个Demo来说明问题:
公共A类
{
公共 A()
{
Console.WriteLine("A的构造函数被调用");
}
}
公共B类:A
{
私有 X x = new X(); //初始化器
}
公开课X
{
公共 X()
{
Console.WriteLine("X的构造函数调用");
}
}
静态无效主(字符串[]参数)
{
B b = 新 B();
}
在调用子类的构造函数之前,会先调用基类的构造函数,那初始化器和基类的构造函数到底谁先执行呢?
因为初始化代码会在构造函数中的代码执行,所以我过去错误的想法是:
公共B类:A
{
私有 X x = new X(); //初始化器
}
等价于:
公共B类:A
{
私人××;
公共 B()
{
x=新X();
}
}
所以我也错误的认为基类的构造函数是在子类的初始化器执行之前的,上面的Demo执行的结果正好相反,是:
X的构造函数调用
A的构造函数被调用
这表明子类的构造器先执行了,让我们看看生成的构造函数的IL代码:
公开B级:A级
{
私人××;
公共 B()
{
x = 新 X();
}
}
生成的构造函数的IL代码是这样的:
.method public hidebysig 特殊名称 rtspecialname
实例 void .ctor() cil 管理
{
// 代码大小 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001:调用实例 void ConsoleApplication1.Program/A::.ctor()
IL_0006:无
IL_0007:无
IL_0008:ldarg.0
IL_0009: newobj 实例 void ConsoleApplication1.Program/X::.ctor()
IL_000e: stfld 类 ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_0013: 没有
IL_0014:返回
} // 方法 B::.ctor 结束
从代码中可以看出是先调用基类的构造函数的!
公共B类:A
{
私有 X x = new X();
}
生成的构造函数的IL代码是这样的:
.method public hidebysig 特殊名称 rtspecialname
实例 void .ctor() cil 管理
{
// 代码大小 19 (0x13)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj 实例 void ConsoleApplication1.Program/X::.ctor()
IL_0006: stfld 类 ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_000b:ldarg.0
IL_000c:调用实例 void ConsoleApplication1.Program/A::.ctor()
IL_0011:无
IL_0012:返回
} // 方法 B::.ctor 结束
可以看出是先调用初始化器的代码,然后再调用基类构造函数的!可见使用初始化器和不使用初始化器还是有区别的,主要区别是基类构造函数的调用顺序不同!
C#编译器为什么这样设计,我也没有想到太合理的原因,大家有什么看法呢?
请大家多多指教啊!
-