C# 字段Initilizers(静态或非静态)和构造函数(静态或非静态),其中一个先运行

C# 字段Initilizers(静态或非静态)和构造函数(静态或非静态),其中一个先运行,c#,.net,visual-studio,constructor,initializer,C#,.net,Visual Studio,Constructor,Initializer,根据我所读到的,有些事情我不清楚: 字段初始值设定项在构造函数之前运行 静态字段初始值设定项在调用静态构造函数之前执行(该构造函数仍与第1点兼容) 如果一个类型没有静态构造函数,字段初始值设定项将在使用该类型之前执行(据我所知:不是实例化而是使用) 本例说明: class Program { static void Main(string[] args) { Console.WriteLine(Foo.X); Console.ReadLine();

根据我所读到的,有些事情我不清楚:

  • 字段初始值设定项在构造函数之前运行
  • 静态
    字段初始值设定项
    在调用
    静态
    构造函数
    之前执行(该构造函数仍与第1点兼容)
  • 如果一个类型没有静态构造函数,
    字段初始值设定项将在使用该类型之前执行(据我所知:不是实例化而是使用)
  • 本例说明:

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Foo.X);
            Console.ReadLine();
        }
    }
    
    class Foo
    {
        public static Foo Instance = new Foo();
        public static int X = 3;
    
        Foo()
        {
            Console.WriteLine("In constructor: " + X);
        }
    }
    
    这段代码打印0,然后打印3!这怎么可能呢?当我们通过执行Foo.X来使用Foo时,在构造函数(到目前为止还可以)之前调用两个初始值设定项,当

    在调用构造函数(第1点)之前,它应该运行自己的2个初始值设定项,而它首先运行构造函数并以0作为默认值打印X

    我真的无法理解这个逻辑,请向我澄清

    编辑:我期望发生的事情:

  • 当Foo.X:execute:public static Foo Instance=new Foo()时
  • 在调用打印的构造函数(“在构造函数中:+X”)之前,公共静态int X=3;应该执行,但构造函数会首先激发,不是假定字段首先完成运行吗?我的意思是,即使在创建新的Foo实例时,也必须首先运行字段
  • 从最后两点开始,我希望打印3,然后打印3
  • Foo()

    因此,首先从上到下初始化字段

    static Foo
    第一次初始化时,它被执行,这就是打印
    0
    的内容,然后当
    X
    被初始化时,这就是使用
    System.Console.WriteLine()调用打印的内容

    如果一个类型没有静态构造函数,字段初始值设定项将在使用该类型之前执行(据我所知:不是实例化而是使用)

    不一定

    如果没有静态构造函数,那么静态字段初始值设定项将在首次使用静态字段之前的某个时间执行-但是静态字段初始值设定项不必在创建任何实例之前执行

    根据C#5规范第10.5.5.1节:

    类的静态字段变量初始值设定项对应于按文本顺序执行的赋值序列,在类声明中以文本顺序出现。如果类中存在静态构造函数(§10.12),则在执行该静态构造函数之前立即执行静态字段初始值设定项。否则,静态字段初始值设定项将在第一次使用该类的静态字段之前的依赖于实现的时间执行

    但是在您的例子中,您刚刚看到当调用
    Foo
    的构造函数来初始化
    实例时,
    X
    仍然是0,因为它没有被赋值。字段初始值设定项是按文本顺序执行的,因此在
    X
    之前为
    Instance
    分配一个值。就这么简单-这不是静态字段和实例字段之间的时间问题,因为您没有任何实例字段


    编辑:看来你被构造函数调用搞糊涂了
    Foo
    已被初始化-构造函数调用不会改变这一点,并且没有“第二次初始化”。构造函数被正常调用,打印“0”,然后返回。然后
    X
    被赋值为3。

    问题是,当调用Foo.X时,它会从上到下执行,当从上到下执行时,它会遇到公共静态Foo Instance=new Foo();它从下到上运行,如果不是,它将永远不会打印0,可能是我,我没有真正捕获它从上到下,
    static Foo Instance
    初始化时调用构造函数,请记住,在未遇到
    static int X
    之前,
    X
    仍然是
    0
    。然后在初始化
    实例
    之后,它还将
    X
    的值分配给
    3
    。然后打印到控制台@AymenDaoudi知道字段初始值设定项是按文本顺序执行的,因此实例在X之前被赋值,问题是当它被赋值(意味着调用构造函数)时,它在将3赋值到X之前就完成了,这怎么可能(第1点)。@AymenDaoudi:它不-它打印0。在执行所有静态初始值设定项后,当打印
    Foo.X
    时,仅打印3#为了更清楚,将构造函数中的代码更改为:
    Console.WriteLine(“构造函数中:+X”)。现在还不清楚您预期会发生什么,但是当您在
    Foo
    类型初始值设定项中调用
    Foo
    的构造函数时,类型初始值设定项已经在运行,因此不会再次单独运行。很抱歉,我可能理解得很慢,我更新了问题,解释了我的想法expect@AymenDaoudi:您说过希望在构造函数执行之前执行
    X=3
    ,但不是为什么。在构造函数完成之前,
    Instance
    的赋值无法完成,这发生在
    X=3
    赋值之前。请注意,这里的两个字段都是静态字段-您看到的只是静态字段初始值设定项调用构造函数的副作用,从而允许查看另一个静态字段的默认值。Thx Jon我现在明白了
    public static Foo Instance = new Foo();