2 {
3 public static int X;
4 static A()
5 {
6 X = B.Y + 1 ;
7 }
8 }
9 public class B
10 {
11 public static int Y = A.X + 1 ;
12 static B()
13 { }
14 }
15 class Program
16 {
17 static void Main( string [] args)
18 {
19 Console.WriteLine( " X={0},Y={1} " , A.X, B.Y);
20 Console.ReadLine();
21 }
22 }
要求写出结果。
当然,因为我不是在面试的情况下遇到这题,所以直接在电脑上运行了,结果是: 。回过头来想想,当执行Console.WriteLine("X={0},Y={1}", A.X, B.Y)一句之时,求取A.X的顺序在前,因此程序首先进入到A的静态构造函数中去计算X的值,而X的值依赖于B的静态成员Y,所以程序应该跳转到B中去求取Y的值,而Y=A.X+1,此时不会再一次进入A中去求取X的值,而是使用整型变量的默认值0,这样计算出来Y的值等于1,返回到A的构造函数中继续计算,得到X的结果为2,符合运行之后得到的结果。为证明我的想法,我在程序中设置断点并单步执行,执行的顺序和我想象一致。
至此,如我一般的菜鸟认为已经没什么问题了。正巧碰到一朋友,此人乃一高手,我将程序发与他,并告知自己所想。朋友看后,很快给我发会一份代码并让我猜测结果,代码如下:
2 {
3 public static int X;
4 static A()
5 {
6 X = B.Y + 1 ;
7 }
8 }
9
10
11 public class B
12 {
13 public static int Y = A.X + 1 ;
14 B()
15 { }
16 }
17
18
19 class Program
20 {
21 static void Main( string [] args)
22 {
23 Console.WriteLine( " X={0},Y={1} " , A.X, B.Y);
24 Console.ReadLine();
25 }
26 }
27
28
我大致一看,似乎还是我发过去的程序,一问之下,原来B的构造函数不再是静态了。B的构造函数体内没有任何代码,我想当然的认为结果还是和原来一样,但运行之后让我大吃一惊,结果居然成了。一个没有任何代码的空构造函数,只是由静态改为非静态,居然会得到完全不同的结果,这真是让我意想不到。看来,在程序的执行过程之上,有一些东西是我所不了解的。还好我懂得“谦受益,满招损”的道理,于是向朋友求教。在朋友的一步步指导之下,终于明白了其中的缘由,整理记录以备遗忘之时查询,也希望如我一般的菜鸟能够从中多少受益。
先考虑最简单的情况,只有Main函数所在的那一个类。我们都知道,对于控制台应用程序,Main函数是入口函数,那么,在程序进入到Main函数之前都发生了些什么呢?我们通过代码来看一看:
2 {
3 public static int num1;
4 public static int num2 = 1 ;
5 public static int num3;
6 static void Main( string [] args)
7 {
8 Console.WriteLine(num2);
9 Console.WriteLine(A.num4);
10 Console.ReadLine();
11 }
12 static Program()
13 {
14 Console.WriteLine(num1);
15 num3 ++ ;
16 Console.WriteLine(num3);
17 }
18 }
我们接着考虑有两个类的情况,还是先看代码:
2 {
3 public static int num1;
4 public static int num2 = 1 ;
5 public static int num3;
6 static void Main( string [] args)
7 {
8 Console.WriteLine(num2);
9 Console.WriteLine(A.num4);//注意在这里引用到了类A的静态成员
10 Console.ReadLine();
11 }
12 static Program()
13 {
14 Console.WriteLine(num1);
15 num3 ++ ;
16 Console.WriteLine(num3);
17 }
18 }
19
20 class A
21 {
22 public static int num4 = 1 ;
23 A()//注意这里是非静态的构造函数
24 {
25 }
26 }
2 {
3 public static int num1;
4 public static int num2 = 1 ;
5 public static int num3;
6 static void Main( string [] args)
7 {
8 Console.WriteLine(num2);
9 Console.WriteLine(A.num4); // 注意这里只引用了类A的成员
10 Console.ReadLine();
11 }
12 static Program()
13 {
14 Console.WriteLine(num1);
15 num3 ++ ;
16 Console.WriteLine(num3);
17 }
18 }
19
20 class A
21 {
22 public static int num4 = 1 ;
23 A()
24 {
25 }
26 }
27
28 class B
29 {
30 public static int num5 = 1 ;
31 B(){} // 注意这里是非静态的构造函数
32 }
在此之前并没有什么让人疑惑之处。接下来我们把上边的代码稍微修改下:
{
public static int num1;
public static int num2 = 1 ;
public static int num3;
static void Main( string [] args)
{
Console.WriteLine(num2);
Console.WriteLine(B.num5); // 这里引用了类B的静态成员
Console.ReadLine();
}
static Program()
{
Console.WriteLine(num1);
num3 ++ ;
Console.WriteLine(num3);
}
}
class A
{
public static int num4 = 1 ;
A() // 注意这里是非静态的构造函数
{
}
}
class B
{
public static int num5 = A.num4 + 1 ; // 类B中引用了类A的静态成员
B(){} // 注意这里是非静态的构造函数
}