创建子对象时构造的顺序
与C++相同,子类创建对象时,要创建对象的基类部分,所以需要在子类的构造函数中隐式调用父类的某个构造函数作为创建实例过程的一部分,继承层次链中的每个类在执行它自己的构造函数体之前先执行它的父类构造函数。
C#中构造顺序与C++有些不同,C#首先会初始化本类中的成员,然后如果这个类有父类则再初始化父类中的成员,然后调用父类的构造函数,最后再执行本类的构造函数,多层次继承亦是如此。下面代码中注释即为执行的顺序。
class A
{
public int a = 100; //3
public A() //4
{
Console.WriteLine("A");
}
}
class B :A
{
public int b = 99; //2
public B():base() //5
{
Console.WriteLine("B");
}
}
class C:B
{
public int i = 10; //1
public C():base() //6
{
Console.WriteLine("C");
}
}
class Program
{
static void Main(string[] args)
{
C c = new C();
}
}
不能在构造函数中调用虚方法
在构造函数中调用虚方法时极不推荐的,在执行基类的构造函数时,基类的虚方法会调用派生类的覆写方法,但这是在执行派生类的构造函数方法体之前,因此调用会在派生类没有完全初始化之前传递到派生类。
子类构造函数中需调用父类的构造函数(base)
默认情况下,在构造对象时,子类的构造函数会自动调用父类的无参构造函数,但构造函数可以重载,所以父类可能有一个以上的构造函数,如果希望子类使用一个指定的父类构造函数而不是无参构造函数,则必须在构造函数初始化语句中指定它。
此语句由关键字base和要调用的基类构造函数的参数列表组成。
使用当前类中其他构造函数作为构造函数初始化语句(this)
另外一种形式的构造函数初始化语句可以让构造过程使用当前类中其他的构造函数。
class A
{
public A(int i):this(i,"aaaaa") { } //此构造函数调用到俩个参数的构造函数
public A() { }
public A(int i, string s)
{
Console.WriteLine(i);
Console.WriteLine(s);
}
}
class Program
{
static void Main(string[] args)
{
A a = new A(100); //100 aaaa
}
}
这种用法很有用的一种情况是,一个类有好几个构造函数,并且它们都需要在对象构造的过程开始时执行一些公共代码,对于这种情况,可以把公共代码提取出来作为一个构造函数,被其他所有的构造函数作为构造函数初始化语句使用,由于减少了重复的代码,实际上这也是推荐的做法。