编写构造函数通常是一件重复性的劳动,我们经常需要在不同声明形式的构造函数中,对同一个成员变量进行同样的初始化操作,为了完成这个任务,通常有以下三种方式。
- 对代码采用“复制/粘贴”的方式,在写好一个构造函数后,将代码粘贴到其他构造函数中。
- 采用辅助函数的方式,将共通的逻辑放置到一个单独的方法中,然后在每个构造函数中调用这个方法。
- 采用构造器链的方式,在一个构造函数中,使用另外的构造函数。
首先,我们要抛弃上述第1种方案,因为重复代码是一种非常明显的代码“坏味道”;对于第2种方案,从消除重复代码的角度来看,是没有问题的,但是产生的目标代码的效率比较低,编译器会在每个构造函数上添加一些代码来执行我们所需要的函数逻辑,它会为每个成员变量添加变量初始化器,并且会调用基类的构造器;而第3种方案,是最简单、最有效率的方式。
我们可以这样使用构造器链。
代码
对于C#对象初始化过程中每一步的顺序,如下。
1 public class MyClass
2 {
3 // collection of data
4 private ArrayList _coll;
5 // Name of the instance:
6 private string _name;
7
8 public MyClass() :
9 this( 0, "" )
10 {
11 }
12
13 public MyClass( int initialCount ) :
14 this( initialCount, "" )
15 {
16 }
17
18 public MyClass( int initialCount, string name )
19 {
20 _coll = ( initialCount > 0 ) ?
21 new ArrayList( initialCount ) :
22 new ArrayList();
23 _name = name;
24 }
25 }
- 将所有的静态变量设置为0
- 执行静态变量初始化器
- 执行基类的静态构造函数
- 执行当前类型的的静态构造函数
- 将所有实例变量设置为0
- 执行实例变量初始化器
- 执行合适的基类实例构造函数
- 执行当前类型的示例构造函数
当创建一个对象时,C#编译器会确保其中的所有变量以某种方式被正确的初始化。至少,我们可以确保创建对象实例时,其所有的内存都设置为0。静态成员和实例成员都遵循这一规则。但我们的目标是确保将所有的变量按照我们期望的方式进行初始化,并且只初始化一次。
我们应该使用变量初始化器来初始化简单的资源。如果需要复杂的逻辑,我们就需要使用构造函数来执行初始化,但这时候我们最好将一些共享的逻辑放在一些构造函数中,然后使用构造函数初始化器来调用它们,从而将代码重复降到最低。