-
构造器是类型的众多成员之一,实例构造器的运行过程是:
- 初始化私有字段;
- 执行父类的构造器;
- 执行自己的构造器的代码;
对于实例构造器和结构,如果不在构造器中对字段进行初始化操作,编译器将自动生成初始化代码,将各字段初始化,如下示例很好的说明了这一点。
using System;
internal struct MyStruct
{
private int x;
private Calculator y;
// override ToString()
public override String ToString()
{
return String.Format("x is {0}, y is {1}", x, y);
}
}
public sealed class Program
{
private int x;
private Calculator y;
// override ToString()
public override String ToString()
{
return String.Format("x is {0}, y is {1}", x, y);
}
public static void Main()
{
MyStruct str = new MyStruct();
Program program = new Program();
// check the values of every field in struct
Console.WriteLine(str);
// check the values of every field in program
Console.WriteLine(program);
}
}
这里用到了使用命令行将类型生成到模块中一小节提到的生成的库CalLibrary.dll中的Calculator类。使用如下命令运行:
csc /r:CalLibrary.dll Program.cs
得到的结果显示,int类型被初始化为0,引用类型为null。这是编译器自动生成初始化代码得到的效果,在使用new 关键字新建对象之前就会运行这些生成的初始化代码。
很多人写代码的时候通常会有如下的风格:
using System;
public sealed class MyClass
{
private int x = 0;
private string a = "Owen";
// constructor
public MyClass() { ... }
...
}
上述代码在声明各字段的时候将字段进行初始化,这样做虽然方便,在大量定义构造器的情况下却严重的影响着性能。无论是有参数还是没有参数的构造器,在开始运行之前都会先运行用于初始化各字段的代码(由编译器生成),如果有很多构造器,则编译器会为每一个构造器生成一段代码做各字段初始化,初始化的过程将重复很多次。
解决这个问题可以将字段初始化放在一个构造器中,运行其他构造器时,指定先运行该起初始化作用的构造器。如下:
public Program()
{
x = 0;
y = new Calculator();
}
public Program(int x) : this()
{
// result in overwriting the value of x which was
// initialized in Program()
this.x = x;
}
注意,结构的构造器不能没有参数,并且有参数时,应该对每一个字段都进行初始化。
internal struct MyStruct
{
private int x;
private string y;
// every field should be initialized
public MyStruct(int x1, string y1)
{
x = x1;
y = y1;
}
}