C# 中静态构造函数/初始值设定项的顺序 [英] Order of static constructors/initializers in C#

查看:22
本文介绍了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?

(回复:Panos)在文件中词汇顺序似乎是王道?跨文件呢?

(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).

推荐答案

这似乎取决于行的顺序.此代码有效:

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] };

虽然这段代码不起作用(它抛出一个 NullReferenceException)

while this code does not work (it throws a 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] };
}

并尝试使用此代码访问它们:

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); }

我们得到这个输出:

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 中的异常,并将字段a 保留为默认值(空).由于anullb也不能正常初始化.

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.

以防万一您没有阅读评论,Jon Skeet 提供了一个非常有趣的阅读:静态构造函数和类型初始化器之间的区别.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆