基类构造函数和初始化器的执行顺序!
标题比较抽象,所以我写了一个Demo来说明问题:
public class A
{
public A()
{
Console.WriteLine("A的构造函数被调用");
}
}
public class B : A
{
private X x = new X(); //初始化器
}
public class X
{
public X()
{
Console.WriteLine("X的构造函数调用");
}
}
static void Main(string[] args)
{
B b = new B();
}
在调用子类的构造函数之前,会先调用基类的构造函数,那初始化器和基类的构造函数到底谁先执行呢?
因为初始化代码会在构造函数中的代码之前执行,所以我过去错误的认为:
public class B : A
{
private X x = new X(); //初始化器
}
等价于:
public class B : A
{
private X x;
public B()
{
x=new X();
}
}
所以我也错误的认为基类的构造函数是在子类的初始化器之前执行的,上面的Demo执行的结果刚好相反,是:
X的构造函数调用
A的构造函数被调用
这表明子类的构造器先执行了,让我们看看生成的构造函数的IL代码:
public class B:A
{
private X x;
public B()
{
x = new X();
}
}
生成的构造函数的IL代码是这样的:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 代码大小 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void ConsoleApplication1.Program/A::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: newobj instance void ConsoleApplication1.Program/X::.ctor()
IL_000e: stfld class ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_0013: nop
IL_0014: ret
} // end of method B::.ctor
从代码可以看出是先调用基类的构造函数的!
public class B : A
{
private X x = new X();
}
生成的构造函数的IL代码是这样的:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 代码大小 19 (0x13)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj instance void ConsoleApplication1.Program/X::.ctor()
IL_0006: stfld class ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_000b: ldarg.0
IL_000c: call instance void ConsoleApplication1.Program/A::.ctor()
IL_0011: nop
IL_0012: ret
} // end of method B::.ctor
可以看出是先调用初始化器的代码,然后再调用基类构造函数的!可见使用初始化器和不使用初始化器还是有区别的,主要区别是基类构造函数的调用顺序不同!
C#编译器为什么这样设计,我也没有想到太合理的原因,大家有什么看法呢?
请大家多多指教啊!
public class A
{
public A()
{
Console.WriteLine("A的构造函数被调用");
}
}
public class B : A
{
private X x = new X(); //初始化器
}
public class X
{
public X()
{
Console.WriteLine("X的构造函数调用");
}
}
static void Main(string[] args)
{
B b = new B();
}
在调用子类的构造函数之前,会先调用基类的构造函数,那初始化器和基类的构造函数到底谁先执行呢?
因为初始化代码会在构造函数中的代码之前执行,所以我过去错误的认为:
public class B : A
{
private X x = new X(); //初始化器
}
等价于:
public class B : A
{
private X x;
public B()
{
x=new X();
}
}
所以我也错误的认为基类的构造函数是在子类的初始化器之前执行的,上面的Demo执行的结果刚好相反,是:
X的构造函数调用
A的构造函数被调用
这表明子类的构造器先执行了,让我们看看生成的构造函数的IL代码:
public class B:A
{
private X x;
public B()
{
x = new X();
}
}
生成的构造函数的IL代码是这样的:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 代码大小 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void ConsoleApplication1.Program/A::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: newobj instance void ConsoleApplication1.Program/X::.ctor()
IL_000e: stfld class ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_0013: nop
IL_0014: ret
} // end of method B::.ctor
从代码可以看出是先调用基类的构造函数的!
public class B : A
{
private X x = new X();
}
生成的构造函数的IL代码是这样的:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 代码大小 19 (0x13)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj instance void ConsoleApplication1.Program/X::.ctor()
IL_0006: stfld class ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_000b: ldarg.0
IL_000c: call instance void ConsoleApplication1.Program/A::.ctor()
IL_0011: nop
IL_0012: ret
} // end of method B::.ctor
可以看出是先调用初始化器的代码,然后再调用基类构造函数的!可见使用初始化器和不使用初始化器还是有区别的,主要区别是基类构造函数的调用顺序不同!
C#编译器为什么这样设计,我也没有想到太合理的原因,大家有什么看法呢?
请大家多多指教啊!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?