C# 静态字段初始化说明及其要求

C# 静态字段初始化说明及其要求,c#,static,static-constructor,C#,Static,Static Constructor,在看了这么多与此相关的复杂问题之后,我想问一下关于以下具有静态字段初始化的代码的解释。我想知道的另一件事是静态字段初始化的要求。在哪种情况下会有帮助 using System; class Test { static void Main() { Console.WriteLine("{0} {1}", B.Y, A.X); } public static int F(string s) { Console.WriteLi

在看了这么多与此相关的复杂问题之后,我想问一下关于以下具有静态字段初始化的代码的解释。我想知道的另一件事是静态字段初始化的要求。在哪种情况下会有帮助

using System;

class Test
{
    static void Main()
    {
        Console.WriteLine("{0} {1}", B.Y, A.X);
    }

    public static int F(string s)
    {
        Console.WriteLine(s);
        return 1;
    }
}

class A
{
    static A()
    { }

    public static int X = Test.F("Init A");
}

class B
{
    static B()
    { }

    public static int Y = Test.F("Init B");
}
输出:

初始B

初始A

11


当不存在静态构造函数时,输出可能会发生变化。我无法理解它背后的原理。静态字段初始化给这个片段带来了什么不同?。有人能帮忙吗。我是c#的新手。

当一个类型有一个静态构造函数时,运行时被限制在第一次使用该类型的任何成员之前立即执行所有类型初始化

当它没有静态构造函数时,运行时就有了更多的自由——它必须在第一次使用静态字段之前或在构造实例之前的某个时间点执行类型初始值设定项,但仅此而已。您甚至可以观察静态方法,这些方法在没有执行类型初始值设定项的情况下,不会接触正在执行的静态字段

在您的例子中,
A
B
都有静态构造函数,对成员的访问顺序是先是B,然后是A,因此是您的输出。如果没有这些静态构造函数,您仍然可以保证得到“11”作为最后一行,并且仍然可以得到“Init A”和“Init B”,但是不能保证它们的顺序

这只是指定语言和运行时的方式,通常没有影响,因为通常类型初始值设定项应该只设置类型,没有其他副作用。理想情况下,类型初始值设定项应该尽可能少地执行操作——如果由于某种原因失败,则该类型将永远无法使用;不会重试类型初始值设定项


有关更多详细信息,请参阅我的和博客文章。

当类型具有静态构造函数时,运行时将被约束为在第一次使用该类型的任何成员之前立即执行所有类型初始化

当它没有静态构造函数时,运行时就有了更多的自由——它必须在第一次使用静态字段之前或在构造实例之前的某个时间点执行类型初始值设定项,但仅此而已。您甚至可以观察静态方法,这些方法在没有执行类型初始值设定项的情况下,不会接触正在执行的静态字段

在您的例子中,
A
B
都有静态构造函数,对成员的访问顺序是先是B,然后是A,因此是您的输出。如果没有这些静态构造函数,您仍然可以保证得到“11”作为最后一行,并且仍然可以得到“Init A”和“Init B”,但是不能保证它们的顺序

这只是指定语言和运行时的方式,通常没有影响,因为通常类型初始值设定项应该只设置类型,没有其他副作用。理想情况下,类型初始值设定项应该尽可能少地执行操作——如果由于某种原因失败,则该类型将永远无法使用;不会重试类型初始值设定项


有关更多详细信息,请参阅我的文章和博客文章。

请在发表文章时花些时间格式化代码。如果没有缩进,读起来真的很难。我只是在格式化后发布的……你想缩进到哪里……请你提一下……这对我以后的文章会有帮助。看看这篇文章现在的样子——所有的缩进都是合适的。现在看看你原来的帖子(点击“编辑”并查看第1版),这篇文章乱七八糟。方法没有缩进,等等。感谢@JonSkeet的反馈。我以后会记住这一点。:)发帖时请花些时间格式化代码。如果没有缩进,读起来真的很难。我只是在格式化后发布的……你想缩进到哪里……请你提一下……这对我以后的文章会有帮助。看看这篇文章现在的样子——所有的缩进都是合适的。现在看看你原来的帖子(点击“编辑”并查看第1版),这篇文章乱七八糟。方法没有缩进,等等。感谢@JonSkeet的反馈。我以后会记住这一点。:)