Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当类具有静态构造函数时,静态字段稍后初始化_C#_.net_Static_Clr_Coreclr - Fatal编程技术网

C# 当类具有静态构造函数时,静态字段稍后初始化

C# 当类具有静态构造函数时,静态字段稍后初始化,c#,.net,static,clr,coreclr,C#,.net,Static,Clr,Coreclr,通过运行以下简单代码: class Program { class MyClassWithStatic { public static int Number = SomeService.GetData(); static MyClassWithStatic() { Console.WriteLine("static ctor runs"); } } class SomeSe

通过运行以下简单代码:

class Program
{
    class MyClassWithStatic
    {
        public static int Number = SomeService.GetData();

        static MyClassWithStatic()
        {
            Console.WriteLine("static ctor runs");
        }
    }

    class SomeService
    {
        public static int GetData()
        {
            Console.WriteLine("GetDataRuns");
            return 42;
        }
    }        

    static void Main(string[] args)
    {
        InitService();

        var value = MyClassWithStatic.Number;
        Console.WriteLine(value);
    }

    private static void InitService()
    {
        Console.WriteLine("InitServiceRuns");
    }
}
我的机器上的输出如下:

InitServiceRuns
GetDataRuns
静态ctor运行
42

这意味着首先调用InitService方法,然后初始化MyClassWithStatic的静态字段,然后调用静态构造函数(事实上,通过在ILSpy和IlDasm中查看这一点,我们可以看到静态字段的初始化发生在cctor的开头)

在这一点上没有什么有趣的,一切都有意义,但是当我移除MyClassWithStatic的静态构造函数时(MyClassWithStatic变成了这个,其他一切都保持原样)

输出如下:

GetDataRuns
InitServiceRuns
42

这意味着,通过删除静态构造函数,静态字段会更早初始化。由于初始化是静态构造函数的一部分(我通过ildasm研究它来说明这一点),其效果基本上是在前面调用静态构造函数

那么问题来了:

  • 有人能解释一下这种行为吗?这是什么原因呢

  • 当调用静态构造函数时,还有什么可以更改的吗? (例如,附加探查器或在IIS中运行它,等等)(我比较了调试、发布模式、x86、x64和所有这些都显示相同的行为)

  • 一些一般的事情:

    -这是在.NET4.6控制台应用程序中实现的。我还切换到了.NET2(应该使用不同的clr运行,行为相同,没有任何区别)

    -我也在.NETCore中尝试了这一点:无论是否使用cctor,都首先调用InitService方法

    -现在我完全意识到:

    用户无法控制何时在中执行静态构造函数 节目

    我也知道在静态构造函数中有很多事情是不应该做的。但不幸的是,我必须处理一个代码,其中这部分超出了我的控制范围,我描述的差异造成了巨大的差异。(我还问了许多与C#cctor有关的SO问题……)


    (还有问题nr3:)那么,我所描述的整个事情不是有点问题吗?

    带有静态构造函数的类将不会被标记为
    beforefieldinit
    标志,这允许运行时稍后对其进行初始化(换句话说,
    MyClassWithStatic.Number
    将在您首次引用/访问
    MyClassWithStatic
    时初始化)

    获取更多信息,请访问

    有人能解释这种行为吗?原因是什么

    @JonSkeet在中有一段关于静态字段和静态构造函数的内容。下面是一个片段:

    C#规范规定:

    • 类的静态构造函数在给定时间内最多执行一次 应用程序域。触发静态构造函数的执行 在应用程序中发生以下事件中的第一个 域:

      • 将创建该类的一个实例
      • 函数的任何静态成员 类被引用
    CLI规范(ECMA 335)规定 第8.9.5节:

    类型可以有类型初始值设定项方法,也可以没有。类型可以是 指定为其类型初始值设定项方法具有宽松语义 (为了下面的方便,我们称之为preforefieldinit之前的放松语义):

    • 如果标记为BeforeFieldInit,则类型的初始值设定项方法为 在首次访问任何静态字段时或之前执行 为该类型定义的
    • 如果未标记为BeforeFieldInit,则该类型为 初始化器方法被执行((在(即,由)触发):首先 访问该类型的任何静态或实例字段,或 调用该类型的任何静态、实例或虚拟方法))
    这将向您展示,当一个类型没有
    beforefieldinit
    标志时,运行时可能会在任意时间调用它,因为它在第一次访问任何定义的静态字段之前,这正是您所看到的

    当静态构造函数 叫什么名字

    唯一的事情就是在你的类型上创建一个静态类型构造函数。否则,你无法控制它的调用

    那么,我描述的整个事情不是有点问题吗


    在哪些方面存在问题?只要您知道自己的目的,我就看不出有问题。CLI规范明确说明了使用类型初始值设定项和不使用类型初始值设定项的保证。因此,如果您遵循这些指导原则,就不会有歧义。

    听起来像。您能描述一下为什么要控制它吗问题在第一个答案中得到了很好的解释,但在哪个方向上需要答案或解决方法?需要什么行为以及可以更改哪些类?实际上,情况是该类只有静态字段(=我的第二个示例)当一个探查器连接到它时,字段会在前面初始化。现在我不知道beforefieldinit标志,所以我尝试添加/删除一个cctor。我不想改变任何东西…我只是想了解原因。所以我们可以告诉你,如果一个类型被标记为beforefieldinit,那么连接一个探查器似乎很难ke a difference(与文档完全同步…)太好了,谢谢!正如您在我的案例中看到的我的评论,该类被标记为beforefieldinit…您知道在这种情况下,如果我附加一个探查器,初始化是否会更早发生吗?(因为这仍然与文档同步)基本上,在理解了这个案例之后,我的第二个问题变成了:“有什么可以改变w
    class MyClassWithStatic
    {
        public static int Number = SomeService.GetData();
    }