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 ...
随机推荐
- python基础之类的isinstance与issubclass、反射
一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo: pass o ...
- 借鉴+总结!! mysql 客户端命令行下 查询数据并生成文件导出
方式1:在mysql命令行环境下执行: sql语句+INTO OUTFILE +文件路径/文件名 +编码方式(可选) 例如: select * from user INTO OUTFILE '/ ...
- Tickets---hdu1260(简单dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1260 题意是有n个人排队买票,第 i 个人买票所需要的时间是a[i],这个人和 i-1 或者 i+1 ...
- 四.mysql演示银行转账
代码演示: #conding:utf8 import pymysql import sys class TransferMoney(object): def __init__(self,conn): ...
- ps如果换背景
一.魔棒工具 魔棒工具主要是使用户可以选择颜色一致的区域(例如,一朵红花)或者背景比较单调的图片,而不必跟踪其轮廓.魔棒工具选择的颜色范围可以由工具选项栏中的误差范围 参数值来控制. 二.钢笔工具 路 ...
- SVG Use(转)
转自:http://www.zhangxinxu.com/wordpress/2014/07/introduce-svg-sprite-technology/ 未来必热:SVG Sprite技术介绍 ...
- 浅析造成 JS 内存泄露的几种原因及解决方案
内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束.在C++中,因为是手动管理内存,内存泄露是经常出现的事情.而现在流行的C#和Java等语言采用了自动垃圾回收方法管理内存,正常使 ...
- linux命令详解之(at)
在Linux下,有两个命令可以用来作为计划任务而执行,at:一次性定时任务计划执行crontab :每天定时任务计划执行 以下仅说一下一次性任务计划执行(at)要使用一次性任务计划,linux必须要有 ...
- MySQL-5.7密码策略及用户资源限制
1.密码策略 在mysql 5.6对密码的强度进行了加强,推出了validate_password 插件.支持密码的强度要求. (1)安装插件 [root@localhost ~]# ll /usr/ ...
- Maven的Mirror和Repository
今天新公司入职,项目经理让迁出项目,心想maven的阿里镜像源挺快的,干脆在配置了公司私服之后自己配置了阿里的镜像源,没成想项目屡屡报错,找不到项目依赖的公司jar包,后来才发现,同事配置mirror ...