此代码在C#中具有明确定义的行为:
class Foo
{
static List<int> to = new List<int>( from ); // from is still null
static IEnumerable<int> from = Something();
}
注意:我不是要问如何将代码修改为I already known how to do that
这有什么理由? C#已经进行了运行时检查,以检测对静态成员的第一次访问。为什么不将它扩展到每个成员的东西并让它们按需运行,甚至更好的让编译器在编译时弄清楚顺序?
BTW:我认为同样的问题(或几乎相同)也适用于非静态成员。
答案 0 :(得分:12)
初始化器只是一种语法糖。编译器在编译类时将该代码放在.cctor中,并将它们放在代码中放置的命令中。
它没有运行任何检查,因为它没有意义。你仍然可以有初始化周期,所以它无论如何都不会工作。
如果你感兴趣的话,我前段时间在博客上写道:
答案 1 :(得分:6)
由于与其他静态类的副作用,我可以设想一个程序员取决于初始化顺序。你和我都知道,根据副作用是不好的做法,但它不一定是非法的。
考虑这样的事情:
class Foo
{
static string header = Bar.GetHeader();
static string version = Bar.GetVersion();
}
Bar.GetVersion
假设已调用Bar.GetHeader
。如果编译器可以自由更改初始化顺序,那么程序员将无法保证初始化顺序。
丑陋,被授予,但完全合法。如果您想象二阶效应(即称为静态方法本身依赖于具有副作用的类),您会发现编译器无法可靠地重新排列任何内容,就像编译器重新排列一样不可能(通常)静态构造函数中函数调用的顺序。
答案 2 :(得分:1)
我认为您需要使用的是静态构造函数。
喜欢这样
class Foo
{
static List<int> to;
static IEnumerable<int> from;
static Foo()
{
from = Something();
to = new List<int>(from);
}
}
至于为什么C#在第一次访问时没有这样做,我只是没有看到需要那种复杂性,当有其他替代方法可以清楚地说明发生了什么。
答案 3 :(得分:1)
C#执行运行时检查以检测对类的第一次访问,但不会在类中重新排序静态初始化。
静态字段从上到下进行初始化,然后是从上到下的静态构造函数。更改字段的顺序或创建静态构造函数并初始化tehre中的字段。
请参阅C#规范中的Variable initializers或初始值设定项上的this article。此外,问题Order of static constructors/initializers in C#也是相关的。