有同学写了以下代码,大家想想结果是怎样的?
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6namespace MyTest
7{
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 C c = new C();
13
14 Console.ReadLine();
15 }
16 }
17
18 class A
19 {
20 public A()
21 {
22 Console.WriteLine("A");
23 }
24 }
25
26 class B
27 {
28 public B()
29 {
30 Console.WriteLine("B");
31 }
32 }
33
34 class C: A
35 {
36 public C()
37 {
38 Console.WriteLine("C");
39 }
40
41 B b = new B();
42 }
43}
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6namespace MyTest
7{
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 C c = new C();
13
14 Console.ReadLine();
15 }
16 }
17
18 class A
19 {
20 public A()
21 {
22 Console.WriteLine("A");
23 }
24 }
25
26 class B
27 {
28 public B()
29 {
30 Console.WriteLine("B");
31 }
32 }
33
34 class C: A
35 {
36 public C()
37 {
38 Console.WriteLine("C");
39 }
40
41 B b = new B();
42 }
43}
呵呵,大家试试看,输出的结果是不是预料之外?
当两个类之间有继承关系时,第一次构造子类的实例时,是按照如下顺序进行的:
- 子类的静态成员初始化语句
- 子类的静态构造函数
- 子类的非静态成员初始化语句
- 父类的静态成员初始化语句
- 父类的静态构造函数
- 父类的非静态成员初始化语句
- 父类的构造函数
- 子类的构造函数
为什么会这样呢?
事实上,出现上述顺序的原因是,在执行完子类的静态构造函数后(也就是第四步),程序会接着执行子类的构造函数,但是,此时,程序会先自动访问该构造函数继承的父类的构造函数(如果没有显式继承,那么就默认继承父类的默认构造函数,如果父类没有默认构造函数,那么会出现编译错误),而且,由于是第一次访问父类,因此会先运行静态成员初始化的代码和静态构造函数。