实例构造器
1、如果类的修饰符为abstract,编译器默认生成的构造器就是protexted
2、如果类为static,则编译器不会再类的定义中生成默认构造器。
static class StaticClassTest
{
public static int a;
}
class NoStaticClassTest
{
public int a;
}
上面一个是静态类,下面则是非静态类,使用ILDasm工具看一下中间代码可以有更加清楚的认识。
可以清楚地看到非静态类会生成一个默认构造器,点开看一下
如果派生类的构造器没有显示调用一个基类构造器。编译器会自动生成对默认的基类构造器的调用,最终会调用到System.Object的公共无参构造器,由于System.Object没有定义实例字段,所以该构造器什么也不做直接返回。
如果在构造引用类型实例时初始化类型中定义的字段。那么编译器会以“内联”的形式初始化实例字段。观察IL代码会发现
class NoStaticClassTest
{
public int a=5;
}
NoStaticClassTest的构造器会先把值5存到字段a,再调用基类的构造器。可以考虑不要在定义字段的时候进行初始化,而是创建单个构造器来执行这些初始化,这样可以减少生成的代码。
例如:
class MyClass
{
private string my = "fff";
private double mz = 5.888;
public MyClass()
{
my = "ssss";
mz = 3.145;
}
public MyClass(Int32 x)
{
}
public MyClass(string s)
{
mz = 10;
}
}
对应无参构造器的IL代码
修改代码,使其不要显示初始化字段
class MyType
{
private string my ;
private double mz;
public MyType()
{
my = "ssss";
mz = 3.145;
}
public MyType(double x):this()
{
mz= x;
}
public MyType(string s) : this()
{
my =s;
}
}
对应无参构造器的IL代码
之前说的都是引用类型,接下来看一下值类型
C#编译器不会为值类型内嵌默认的无参构造器,但是允许为值类型显式定义构造器,并且要注意以下几点:
1、不能显示定义无参数构造器
2、不能内联实例字段的初始化
3、在定义的构造器中必须为所有的字段进行赋值。
类型构造器
类型构造器也称为静态构造器,只执行一次,定义也只能定义一个,类型构造器总是私有,并且永远没有参数,因为对于他的调用是由CLR执行的。
class NoStaticClassTest
{
public static int a=55;
}
生成上述代码时,编译器会自动生成一个类型构造器,查看IL代码可以看出
会多出一个**.cctor**的方法,就是类型构造器。
.cctor 方法总是默认 private 和 static 的。
class NoStaticClassTest
{
public static int a = 55;
static NoStaticClassTest(){
a=60;
}
}
如果是上述代码,编译器也只是生成一个类型构造器,先将a初始化为55,再修改成60。