C# 静态变量初始化顺序的一个问题

今天在写 C# 的时候遇到下面这样一个问题。

首先我们大多数人知道,如果有一个静态类像这样:

1
2
3
4
5
public static class c1
{
public static int v1 = 256;
public static int v2 = v1;
}

然后打印 v2 会得到 256。

而如果它是:

1
2
3
4
5
public static class c1
{
public static int v2 = v1;
public static int v1 = 256;
}

然后打印 v2 会得到 0。

这是由它声明顺序决定的。

但是如果静态成员变量 v1, v2 在不同的类中,情况就没有这么简单。如果有这么两个类:

1
2
3
4
5
6
7
8
9
public static class c1
{
public static int v1 = 256;
}

public static class c2
{
public static int v2 = c1.v1;
}

此时不管是以上面这样的顺序声明两个类,还是换一下顺序:

1
2
3
4
5
6
7
8
9
public static class c2
{
public static int v2 = c1.v1;
}

public static class c1
{
public static int v1 = 256;
}

打印 c2.v2 的结果都是 256。

这时我就纳闷了,就跟朋友们讨论了一下,他们说可能是因为编译器很智能,会根据类之间的依赖关系来决定初始化顺序。那么就有新的问题了,如果他们相互依赖的话,情况又是怎么样呢?

为了测试,把两个类改成这样:

1
2
3
4
5
6
7
8
9
10
11
public static class c1
{
public static int v1 = 256;
public static int v2 = c2.v1;
}

public static class c2
{
public static int v1 = 1024;
public static int v2 = c1.v1;
}

此时先后打印 c1.v2, c2.v2, 会得到结果:

1
2
1024    // c1.v2
0 // c2.v2

即使我调换了 c1, c2 的声明顺序,也是得到这个结果。

但是,如果我换一下打印顺序,先打印 c2.v2, 再打印 c1.v2, 结果是:

1
2
256    // c2.v2
0 // c1.v2

也就是说,在这种情况下,会根据代码的执行顺序来决定初始化顺序。不会报错,也不会报警告。

而这通常不是我们想要的。在编码过程中要尽量避免把代码写成这种情况,我们不应该依赖智能的编译器。

樱井政博 SubsetGames
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×