C# 构造函数调用顺序
了解C#的一个类的加载过程,对于语言机制的理解和写出高效的语言很有帮助,这里简单介绍一下类的实例的构造函数调用过程。
C#类的实例的构造过程是,先为实例的数据字段分配内存,并对所有字段按字节置零(0或者null);然后初始化附加内存(类型对象指针和同步块索引);调用类型的实例构造器(也就是new关键字调用的普通构造函数)初始化字段。
假如有两个类:基类BaseClass和派生类DerivedClass。DerivedClass继承BaseClass。
namespace GenericSyntax.Constructor
{
class BaseClass
{
public BaseClass()
{
Console.WriteLine("Base class Ctor.");
}
} class DerivedClass:BaseClass
{
private string m_Var1 = "Assigned in declaration.";
private string m_Var2;
public DerivedClass()
{
Console.WriteLine(m_Var2==null);
Console.WriteLine(m_Var1);
m_Var1 = "Assigned in constructor of derived Class.";
Console.WriteLine("Derived class Ctor.");
}
public override string ToString()
{
return m_Var1;
}
}
}
namespace GenericSyntax
{
class Program
{
static void Main(string[] args)
{
TestCtor();
Console.ReadKey();
}
private static void TestCtor()
{
Constructor.DerivedClass instance = new
Constructor.DerivedClass();
Console.WriteLine(instance.ToString());
}
}
}
生成的BaseClass的IL和DerivedClass的IL如下:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 代码大小 20 (0x14)
.maxstack
IL_0000: ldarg.
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldstr "Base class Ctor."
IL_000d: call void [mscorlib]System.Console::WriteLine(string)
IL_0012: nop
IL_0013: ret
} // end of method BaseClass::.ctor
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 代码大小 69 (0x45)
.maxstack
IL_0000: ldarg.
IL_0001: ldstr "Assigned in declaration."
IL_0006: stfld string GenericSyntax.Constructor.DerivedClass::m_Var1
IL_000b: ldarg.
IL_000c: call instance void GenericSyntax.Constructor.BaseClass::.ctor()
IL_0011: nop
IL_0012: nop
IL_0013: ldarg.
IL_0014: ldfld string GenericSyntax.Constructor.DerivedClass::m_Var2
IL_0019: ldnull
IL_001a: ceq
IL_001c: call void [mscorlib]System.Console::WriteLine(bool)
IL_0021: nop
IL_0022: ldarg.
IL_0023: ldfld string GenericSyntax.Constructor.DerivedClass::m_Var1
IL_0028: call void [mscorlib]System.Console::WriteLine(string)
IL_002d: nop
IL_002e: ldarg.
IL_002f: ldstr "Assigned in constructor of derived Class."
IL_0034: stfld string GenericSyntax.Constructor.DerivedClass::m_Var1
IL_0039: ldstr "Derived class Ctor."
IL_003e: call void [mscorlib]System.Console::WriteLine(string)
IL_0043: nop
IL_0044: ret
} // end of method DerivedClass::.ctor
可以看出,则初始化DerivedClass时,DerivedClass的构造函数的IL代码顺序执行如下
1. 解析派生类实例字段的直接赋值语句,即:如果字段有直接赋值语句,则用该赋值语句或者字面量对字段进行赋值。
2. 调用基类的构造函数(逐级向上调用,知道Object的构造函数),基类的实例化过程同理。
3. 执行派生类该实例构造函数的函数体。
执行代码如下:

C# 构造函数调用顺序的更多相关文章
- java初始化构造函数调用顺序
类初始化时构造函数调用顺序: (1)初始化对象的存储空间为零或null值: (2)调用父类构造函数: (3)按顺序分别调用类成员变量和实例成员变量的初始化表达式: (4)调用本身构造函数. 例子 ...
- C++派生类构造函数调用顺序(详解)
我们来看下面一段代码: class B1 { public: B1(int i) {cout<<"constructing B1 "<<i<<e ...
- JAVA & .NET创建对象构造函数调用顺序
JAVA 定义Person类 package models; public class Person { public Person() { System.out.println("pe ...
- C++ 全局构造函数调用的顺序
C++的全局类和静态类的构造函数是在main函数之前调用的.但是,不同的类的构造函数以什么顺序调用呢? 对于g++编译器来说,这个顺序是由链接时,文件顺序决定的. 我们用一个例子来说明这一点. 我们有 ...
- c++深/浅拷贝 && 构造函数析构函数调用顺序练习题
1.深/浅拷贝 编译器为我们提供的合成拷贝构造函数以及合成的拷贝赋值运算符都是浅拷贝.浅拷贝只是做简单的复制,如果在类的构造函数中new出了内存,浅拷贝只会简单的复制一份指向该内存的指针,而不会再开辟 ...
- [Effective JavaScript 笔记]第18条:理解函数调用、方法调用及构造函数调用之间的不同
面向对象编程中,函数.方法.类的构造函数是三种不同的概念. JS中,它们只是单个构造对象的三种不同的使用模式. 三种不同的使用模式 函数调用 function hello(username){ ret ...
- C++中构造函数调用构造函数
今天想做道矩阵的题目时,却卡在一些编程细节上了,找了好久才发现原来是在构造函数处出了问题,然后上网百度了下,发现这篇文章说得很好:从一道题谈C++中构造函数调用构造函数,很棒! 还补充一点: 看来自己 ...
- 你不知道的JavaScript--Item8 函数,方法,构造函数调用
1.函数调用 Function绝对是JavaScript中的重中之重.在JavaScript中,Function承担了procedures, methods, constructors甚至是class ...
- C++类中一个构造函数调用另一个构造函数
class A { int a; int b; int c; public: A(int aa, int bb) : a(aa), b(bb),c(0) { cout << "a ...
随机推荐
- Android图片加载框架Picasso最全使用教程1
Picasso介绍 Picasso是Square公司开源的一个Android图形缓存库 A powerful image downloading and caching library for And ...
- PScc
photoshop cc 2018破解版是Adobe公司最新版专业化CC图像处理软件,新功能超乎你的想象!photoshop cc 2018破解版新功能给力来袭,访问Lightroom照片,分享作 ...
- Oracle DG备库强制switch_over过程
故障描述: 主库异常下线,需要将备库强制启动为主库,切断日志时提示需要介质恢复,执行介质恢复后,再激活日志即可进行切换 1. 执行alter database recover managed sta ...
- 如何实现关系表的级联删除(ON DELETE CASCADE的用法)
以下面两张表为例: SQL> desc person 名称 是否为空? 类型 --------------------- ...
- c++ 11 bind function
Year 2011陈 良乔C++11 FAQ std::function 和 std::bind 标准库函数bind()和function()定义于头文件中(该头文件还包括许多其他函数对象),用于处理 ...
- 微信小程序学习笔记(4)--------框架之逻辑层
逻辑层 逻辑层(App Service):小程序框架的逻辑层是由JavaScript编写的,逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈. App进行程序注册,Page进行页面注册 g ...
- win7解压的软件开机自启动
win7让你一个可执行程序开机启动. 运行-->regedit-->HKEY_LOCAL_MACHINE-->SOFTWARE-->Microsoft-->Windows ...
- Java遍历List集合的三种方法
Java遍历List集合的三种方法 List<String> list = new ArrayList<String>(); list.add("aaa") ...
- 纯CSS3滑动开关按钮
在线演示 本地下载
- jQuery双向滑动杆 设置数值百分比
在线演示 本地下载