静态字段初始化顺序(C#) - 有人可以解释这个片段吗?

voi*_*tar 5 c# static-members

我是一名学习C#的C++程序员.我目前正在Nutshell中阅读C#4.0.

我在第74页上发表了这句话/ snipet:

静态字段初始值设定项按声明字段的顺序运行.以下示例说明了这一点:X初始化为0,Y初始化为3.

class Foo
{
    public static int X = Y; // 0
    public static int Y = 3; // 3
}
Run Code Online (Sandbox Code Playgroud)

我不明白如何在Y中分配值,而不首先声明Y. 我在这里错过了什么吗?

顺便说一下,来自C++背景,我倾向于使用术语ctor作为构造函数 - 但是,我还没有在C#中使用这个术语 - ctor世界中也使用了ctor一词吗?

[编辑]

同一页面上的另一个例子(在前面提到的书中)是这样的:

class Program
{
    static void Main() { Console.WriteLine (Foo.X); } // 3
}
class Foo
{
    public static Foo Instance = new Foo();
    public static int X = 3;
    Foo() { Console.WriteLine (X); } // 0
}
Run Code Online (Sandbox Code Playgroud)

该书陈述(上例):

该示例打印0后跟3,因为实例化Foo的字段初始值设定项在X初始化为3之前执行:

我在这些例子中还有一些问题.

  1. 这两个示例都出现在标题为静态构造函数和字段初始化顺序的部分下,但代码示例中没有显示静态ctor - 至少不是我能够轻易识别的.我期待一个静态ctor与该类具有相同的名称,是无参数的,并且前面是' static '关键字.所以我不明白这些例子与章节标题的关系.我在这里错过了什么?

  2. 在第二个例子中,(非静态)ctor打印出X的值 - 在前一行中明确赋值为3 - 然而,打印出的输出为0.为什么?!

Jon*_*eet 7

就这里提供的内容而言,声明顺序并不重要.它不像是局部变量的情况,变量只有在声明后才可用.实例变量 - 实际上是方法也是如此,其中在源中先前声明的方法可以调用稍后在源中声明的方法,等等.

但是,声明的顺序在初始化程序的执行方面重要,这就是你获得这种行为的原因.请注意,如果将这些变量更改为const,则两者都将取值3 - 编译器将计算出所需的评估顺序,并将检测是否存在任何循环(这会导致错误).然后在编译时评估常量,并将值直接嵌入IL中.

有关什么是有效等的更多详细信息,请参阅规范.

至于术语 - 我通常不认为有必要将"构造函数"缩写为"ctor",尽管我认为通常会理解它.我可以将该缩写用作变量名,例如:

var ctor = typeof(...).GetConstructor(...);
Run Code Online (Sandbox Code Playgroud)

  • 如果将这些变量更改为const,它们只是常量值,没有初始化. (2认同)

mel*_*okb 5

在C#中,原始类型如int采用默认值.因为int,默认值为0.这与C++不同,您必须初始化值,否则它将从内存中获取随机脏值.由于已知Y是类型int,因此可以为X指定其默认值0.

至于关键字ctor,我不认为它非常像C#程序员,但我对这个术语很熟悉.我相信它在Visual Studio的一些地方使用,例如在对象浏览器中.

  • @voidstar:编译器不需要在使用之前声明所有内容 - 它执行几个编译阶段.您可以假设,当它做出这样的决定时,它可以看到整个代码. (3认同)
  • `ctor`也是IL中使用的术语(`cctor`用于静态构造函数) (2认同)