C# C中的静态字段初始化顺序#

C# C中的静态字段初始化顺序#,c#,.net,oop,clr,C#,.net,Oop,Clr,我找到了链接,找到了下面的代码片段。我很想尝试一下这个片段,以获得不确定的输出 以下代码段: 可能会产生以下任一输出: 初始A 初始B 11 或输出: 初始B 初始A 11 然而,由于某些原因,我总是得到第二个输出。无论我运行/重建/构建多少次 谁能给我解释一下: 为什么只有B类先被执行?如果我把电话倒过来 'A.X,B.Y',则只首先执行类A 如何模拟不确定的行为 为什么只有B类先被执行 规范说明两个输出都是有效的。但是编译器和运行时的特定组合(例如运行在.NETFramework4.7上的C

我找到了链接,找到了下面的代码片段。我很想尝试一下这个片段,以获得不确定的输出

以下代码段:

可能会产生以下任一输出:

初始A

初始B

11

或输出:

初始B

初始A

11

然而,由于某些原因,我总是得到第二个输出。无论我运行/重建/构建多少次

谁能给我解释一下:

  • 为什么只有B类先被执行?如果我把电话倒过来 'A.X,B.Y',则只首先执行类A
  • 如何模拟不确定的行为
  • 为什么只有B类先被执行

    规范说明两个输出都是有效的。但是编译器和运行时的特定组合(例如运行在.NETFramework4.7上的C#7.0编译器)可以决定更加严格,并且行为一致

    您使用的组合似乎决定首先初始化首先使用的类的静态字段,根据规范,这样做是可以接受的

    如何模拟不确定的行为

    同样,本规范不要求任何不确定性

    如果您真的想让它以这种方式运行,您可以修改现有的.Net运行时(如CoreCLR、Mono或),找到所有可能的初始化顺序,然后随机选择一个

    为什么只有B类先被执行

    规范说明两个输出都是有效的。但是编译器和运行时的特定组合(例如运行在.NETFramework4.7上的C#7.0编译器)可以决定更加严格,并且行为一致

    您使用的组合似乎决定首先初始化首先使用的类的静态字段,根据规范,这样做是可以接受的

    如何模拟不确定的行为

    同样,本规范不要求任何不确定性


    如果您真的想让它以这种方式运行,您可以修改现有的.Net运行时(如CoreCLR、Mono或),以找到所有可能的初始化顺序,然后随机选择一个。

    如果您只是在同一台机器上针对同一CLR运行,则不太可能看到变化。不确定性和灵活性允许JIT编译器的不同实现。如果执行顺序与代码所需的顺序相关,我不会感到惊讶-如果不需要,为什么要初始化某些东西。如果您使用“B.Y,B.Y”调用,那么我希望A.X没有初始化。充分阅读您的链接,我看到的措辞是:“否则,静态字段初始化器在第一次使用该类的静态字段之前在依赖于实现的时间执行。”然后“它们仅限于在引用这些字段之前出现“。因此,实际上它所说的是,初始化必须在首次使用之前完成&这取决于实现来决定何时-这不同于说行为不确定-可能以任意顺序发生。如果您只是在同一台机器上针对同一CLR运行,您不太可能看到变化。不确定性和灵活性允许JIT编译器的不同实现。如果执行顺序与代码所需的顺序相关,我不会感到惊讶-如果不需要,为什么要初始化某些东西。如果您使用“B.Y,B.Y”调用,那么我希望A.X没有初始化。充分阅读您的链接,我看到的措辞是:“否则,静态字段初始化器在第一次使用该类的静态字段之前在依赖于实现的时间执行。”然后“它们仅限于在引用这些字段之前出现”。因此,实际上它所说的是,初始化必须在首次使用之前完成&这取决于实现来决定何时——这与说行为是不确定的不同&可能以任意顺序发生。
    using System;
    class Test
    {
       static void Main() 
       {  // Breakpoint here is skipped and control goes to Class B then Class A
          // Why control is always going to Class B first?
          Console.WriteLine("{0} {1}", B.Y, A.X);
       }
       public static int F(string s) {
          Console.WriteLine(s);
          return 1;
       }
    }
    class A
    {       // 
       public static int X = Test.F("Init A");
    }
    class B
    {       // Debugging always starts here.
       public static int Y = Test.F("Init B");
    }