5

如果我们的项目中还有一个静态类,哪个静态类首先初始化?

例如:下面的代码给出了空异常。

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类首先初始化,那么SecondfirstArray将为空。我试图告诉哪个初始化首先会产生不同的结果。

我认为这是关于我的项目的抽象问题。我在试图理解为什么我得到意想不到的结果时遇到了它。

4

2 回答 2

10

First将开始初始化,赋值firstArray,然后注意到它需要Second被初始化才能得到 的初始值secondArray

Second将开始初始化,然后注意到它需要 First 进行初始化。但是,CLR 会注意到 First已经在当前线程中初始化,所以它不会阻塞。Second的初始化将完成,然后First的初始化将完成。

幸运的是,Second需要的字段已经被分配,所以“正确的事情”发生了。

如果First 实际上首先开始初始化,那就太好了。但是,由于这两个类都没有静态构造函数,因此可能Second会首先开始初始化......然后它会开始初始化First,这将发现Second已经在初始化并Second.secondArrayFirst.secondArray. 这将是一件坏事。请注意,在 .NET 4 中,没有静态构造函数的类型的初始化时间发生了变化——不是以破坏规范的方式,但可能是以破坏现有代码的方式。

如果两者都First具有Second静态构造函数,那么First将首先初始化,因为这是第一个Main涉及的类。

答案的道德:不要这样做。相互引用的类型初始化器非常容易出错。另一个示例,请参阅 Eric Lippert 和 Neal Gafter 在 NDC 2010 的演讲“C# Puzzlers”,可以在NDC 视频页面上观看。

于 2010-07-01T11:26:07.953 回答
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());
    }
}

现在,当你再次运行相同的东西时,它可以工作......

于 2010-07-01T11:30:10.130 回答