标题比较抽象,所以我写了一个Demo来说明问题:
คลาสสาธารณะ A
-
สาธารณะ A()
-
Console.WriteLine("A ของฉัน");
-
-
คลาสสาธารณะ B : A
-
ส่วนตัว X x = X ใหม่ (); //初始化器
-
คลาสสาธารณะ X
-
สาธารณะ X()
-
Console.WriteLine("X 构造函数调用");
-
-
โมฆะคงที่หลัก (สตริง [] args)
-
B b = ใหม่ B();
-
在调用子类的构造函数之前,会先调用基类的构造函数,那初始化器和基类的构造函数到底谁先执行呢?
因为初始化代码会在构造函数中的代码之前执行,所以我过去错误的认为:
คลาสสาธารณะ B : A
-
ส่วนตัว X x = X ใหม่ (); //初始化器
-
等价于:
คลาสสาธารณะ B : A
-
ส่วนตัว X x;
สาธารณะ B()
-
x=ใหม่ X();
-
-
所以我也错误的认为基类的构造函数是在子类的初始化器之前执行的,上的Demo执行的结果刚好相反,是:
X的构造函数调用
A的构造函数被调用
这表明子类的构造器先执行了,让我们看看生成的构造函数的IL代码:
คลาสสาธารณะ B:A
-
ส่วนตัว X x;
สาธารณะ B()
-
x = X ใหม่();
-
-
生成的构造函数的IL代码是这样的:
.method สาธารณะ Hidebysig ชื่อพิเศษ rtspecialname
อินสแตนซ์เป็นโมฆะ .ctor() cil ได้รับการจัดการ
-
// 代码ตัวใหญ่ตัวเล็ก 21 (0x15)
.maxstack8
IL_0000: ldarg.0
IL_0001: การเรียกอินสแตนซ์เป็นโมฆะ ConsoleApplication1.Program/A::.ctor()
IL_0006: ไม่
IL_0007: ไม่
IL_0008: ldarg.0
IL_0009: อินสแตนซ์ newobj ถือเป็นโมฆะ ConsoleApplication1.Program/X::.ctor()
IL_000e: คลาส stfld ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_0013: ไม่
IL_0014: ถอนตัว
} // สิ้นสุดวิธี B::.ctor
从代码可以看出是先调用基类的构造函数的!
คลาสสาธารณะ B : A
-
ส่วนตัว X x = X ใหม่ ();
-
生成的构造函数的IL代码是这样的:
.method สาธารณะ Hidebysig ชื่อพิเศษ rtspecialname
อินสแตนซ์เป็นโมฆะ .ctor() cil ได้รับการจัดการ
-
// 代码ตัวใหญ่ตัวเล็ก 19 (0x13)
.maxstack 8
IL_0000: ldarg.0
IL_0001: อินสแตนซ์ newobj ถือเป็นโมฆะ ConsoleApplication1.Program/X::.ctor()
IL_0006: คลาส stfld ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_000b: ldarg.0
IL_000c: การเรียกอินสแตนซ์เป็นโมฆะ ConsoleApplication1.Program/A::.ctor()
IL_0011: ไม่
IL_0012: ถอนตัว
} // สิ้นสุดวิธี B::.ctor
可以看出是先调用初始化器的代码,然后再调用基类构造函数的!可见使用初始化器和不使用初始化器还是有区别的,主要区别是基类构造函数的调用顺序不同!
C#编译器为什么这样设计,我也没有想到太合理的原因,大家有什么看法呢?
请大家多多指教啊!
-