如果我们的项目中还有一个静态类,那么首先初始化哪个静态类?
例如:下面的代码给出了null异常。
class Program
{
static void Main(string[] args)
{
First.Write();
Second.Write();
}
}
static class First
{
public static int[] firstArray = new int[20];
public static int[] secondArray = Second.secondArray;
public static void Write()
{
Console.WriteLine(firstArray.ToString());
Console.WriteLine(secondArray.ToString());
}
}
static class Second
{
public static int[] firstArray = First.firstArray;
public static int[] secondArray = new int[30];
public static void Write()
{
Console.WriteLine(firstArray.ToString());
Console.WriteLine(secondArray.ToString());
}
}
如果您注意,您会看到如果First
类会自行初始化,那么secondArray
Second
字段将为空。但是如果Second
类首先初始化,那么Second
类firstArray
将为空。我试图告诉哪个初始化首先产生不同的结果。
我认为这是关于我的项目的抽象问题。我在试图理解为什么会得到意想不到的结果时遇到它。
答案 0 :(得分:10)
First
将开始初始化,分配firstArray
,然后注意它需要初始化Second
才能获得secondArray
的初始值。
Second
将开始初始化,然后注意它需要First进行初始化。但是,CLR会注意到First在当前线程中已经已经初始化,因此它不会阻塞。 <{1}}的初始化将完成,然后First的初始化将完成。
幸运的是,已经分配了Second
所需的字段,因此发生了“正确的事情”。
如果Second
实际上首先开始初始化,那就非常好了。但是,由于这两个类都没有静态构造函数,First
可能会首先开始初始化...然后它会开始初始化Second
,这会发现First
是已经初始化并获取Second
的{{1}}当前值(null)。这将是一件坏事。请注意,没有静态构造函数的类型的初始化时序为changed in .NET 4 - 不是以破坏规范的方式,而是可能以现有代码破坏的方式。
如果Second.secondArray
和First.secondArray
都有静态构造函数,那么First
将首先被初始化,因为这是Second
触及的第一个类。
答案的道德:不要这样做。相互引用的类型初始化器非常容易出错。再举一个例子,请参阅Eric Lippert和Neal Gafter的NDC 2010演讲,“C#Puzzlers”,可在NDC video page上查看。
答案 1 :(得分:0)
我不相信有关哪个静态类型首先被初始化的保证。要确保以这种方式正确初始化字段,您需要添加静态构造函数,例如:
static class Second
{
public static int[] firstArray = First.firstArray;
public static int[] secondArray = new int[30];
static Second() { }
public static void Write()
{
Console.WriteLine(firstArray.ToString());
Console.WriteLine(secondArray.ToString());
}
}
现在,当你再次运行同样的东西时,它会起作用......