在C#静态构造函数/初始化顺序 [英] Order of static constructors/initializers in C#
问题描述
虽然在C#应用程序工作,我只注意到在几个地方静态初始化对相互依存关系是这样的:
While working on a C# app I just noticed that in several places static initializers have dependencies on each other like this:
static private List<int> a = new List<int>() { 0 };
static private List<int> b = new List<int>() { a[0] };
如果没有什么特别的工作。是不是只是运气? C#有规则来解决此问题?
Without doing anything special that worked. Is that just luck? Does C# have rules to resolve this?
编辑:(RE:帕诺斯)在一个文件词法顺序似乎是王吗?什么跨文件?
(re: Panos) In a file lexical order seems to be king? what about across files?
在找我尝试了周期性的依赖关系是这样的:
In looking I tried a cyclical dependency like this:
static private List<int> a = new List<int>() { b[0] };
static private List<int> b = new List<int>() { a[0] };
和程序没有运行相同的(测试服全线失败,我没有进一步看)。
and the program didn't run the same (the test suit failed across the board and I didn't look further).
推荐答案
这似乎取决于线路的顺序。这code工作:
It seems to depend on the sequence of lines. This code works:
static private List<int> a = new List<int>() { 1 };
static private List<int> b = new List<int>() { a[0] };
而这code不工作(它抛出一个的NullReferenceException
)
static private List<int> a = new List<int>() { b[0] };
static private List<int> b = new List<int>() { 1 };
所以,很明显存在周期性的依赖没有规则。它的奇特但是编译器不会抱怨...
So, obviously no rules for cyclical dependency exist. It's peculiar however that the compiler does not complain...
编辑 - 发生了什么跨文件?如果我们声明这两个类:
EDIT - What's happening "across files"? If we declare these two classes:
public class A {
public static List<int> a = new List<int>() { B.b[0] };
}
public class B {
public static List<int> b = new List<int>() { A.a[0] };
}
和尝试这个code来访问它们:
and try to access them with this code:
try { Console.WriteLine(B.b); } catch (Exception e) { Console.WriteLine(e.InnerException.Message.); }
try { Console.WriteLine(A.a); } catch (Exception e) { Console.WriteLine(e.InnerException.Message); }
try { Console.WriteLine(B.b); } catch (Exception e) { Console.WriteLine(e.InnerException.Message); }
我们得到这样的输出:
we are getting this output:
The type initializer for 'A' threw an exception.
Object reference not set to an instance of an object.
The type initializer for 'A' threw an exception.
所以 B
的初始化导致异常的静态构造函数 A
和左派领域一个
使用默认值(NULL)。由于 A
是空
, B
不能也被初始化正常。
So the initialization of B
causes an exception in static constructor A
and lefts field a
with the default value (null). Since a
is null
, b
can not also be initialized properly.
如果我们没有周期性的依赖,一切工作正常。
If we do not have cyclical dependencies, everything works fine.
编辑:万一你没读过的评论,乔恩斯基特提供了一个非常有趣的阅读: 静态构造函数之间的差异,并输入初始化的。
Just in case you didn't read the comments, Jon Skeet provides a very interesting reading: The differences between static constructors and type initializers.
这篇关于在C#静态构造函数/初始化顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!