Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C中静态构造函数/初始值设定项的顺序#_C#_Static_Dependencies_Internals - Fatal编程技术网

C# C中静态构造函数/初始值设定项的顺序#

C# C中静态构造函数/初始值设定项的顺序#,c#,static,dependencies,internals,C#,Static,Dependencies,Internals,在开发C#应用程序时,我注意到在一些地方,静态初始值设定项相互依赖,如下所示: static private List<int> a = new List<int>() { 0 }; static private List<int> b = new List<int>() { a[0] }; static private List<int> a = new List<int>() { b[0] }; static priv

在开发C#应用程序时,我注意到在一些地方,静态初始值设定项相互依赖,如下所示:

static private List<int> a = new List<int>() { 0 };
static private List<int> b = new List<int>() { a[0] };
static private List<int> a = new List<int>() { b[0] };
static private List<int> b = new List<int>() { a[0] };
static private List a=new List(){0};
静态私有列表b=新列表(){a[0]};
没有做任何特别有效的事情。这只是运气吗?C#有规则来解决这个问题吗

编辑:(re:Panos)在文件中的词法顺序似乎是最重要的?那么跨文件呢

在寻找过程中,我尝试了如下循环依赖:

static private List<int> a = new List<int>() { 0 };
static private List<int> b = new List<int>() { a[0] };
static private List<int> a = new List<int>() { b[0] };
static private List<int> b = new List<int>() { a[0] };
static private List a=new List(){b[0]};
静态私有列表b=新列表(){a[0]};

而且程序也没有运行相同的程序(测试套装全部失败,我没有进一步查看)。

这似乎取决于行的顺序。此代码适用于:

static private List<int> a = new List<int>() { 1 };
static private List<int> b = new List<int>() { a[0] };
因此,显然不存在周期性依赖的规则。但奇怪的是,编译器并没有抱怨


编辑-文件之间发生了什么?如果我们声明这两类:

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] };
}
我们将获得以下输出:

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
和lefts字段
A
中导致一个异常,并使用默认值(null)。由于
a
null
b
也无法正确初始化

如果我们没有周期性的依赖关系,那么一切都很好


编辑:为了防止你没有读到评论,提供了一个非常有趣的阅读:。

是的,你很幸运。C#显示为按照代码在类中的显示顺序执行代码

static private List<int> a = new List<int>() { 0 };
static private List<int> b = new List<int>() { a[0] };
static private List a=new List(){0};
静态私有列表b=新列表(){a[0]};
会有用的,但是

static private List<int> b = new List<int>() { a[0] };
static private List<int> a = new List<int>() { 0 };
static private List b=new List(){a[0]};
静态私有列表a=新列表(){0};
将失败

我建议将所有依赖项放在一个地方,静态构造函数就是这个地方

static MyClass()
{
  a = new List<int>() { 0 };
  b = new List<int>() { a[0] };
}
静态MyClass()
{
a=新列表(){0};
b=新列表(){a[0]};
}

就我个人而言,我会去掉静态初始值设定项,因为它不清楚,并添加一个静态构造函数来初始化这些变量

static private List<int> a;
static private List<int> b;

static SomeClass()
{
    a = new List<int>() { 0 };
    b = new List<int>() { a[0] };
}
静态私有列表a;
静态私有列表b;
静态类()
{
a=新列表(){0};
b=新列表(){a[0]};
}
这样你就不必猜测发生了什么,你的意图也就很清楚了。

请参阅此处的规则:

初始化类时,该类中的所有静态字段首先初始化为其默认值,然后按文本顺序执行静态字段初始值设定项。类似地,创建类的实例时,该实例中的所有实例字段首先初始化为其默认值,然后按文本顺序执行实例字段初始值设定项。具有变量初始值设定项的静态字段可以在其默认值状态下观察到。然而,这是强烈反对的风格问题

换句话说,在您的示例中,“b”被初始化为其默认状态(null),因此在“a”的初始值设定项中对它的引用是合法的,但会导致NullReferenceException


这些规则与Java的不同(请参阅Java关于转发引用的规则,这些规则更具限制性)。

回答了我的问题。然而,我似乎并没有问我想问的问题:跨文件如何?我不是一个C#whiz(只是知道去哪里看),但请注意--“可以构造循环依赖项,允许在默认值状态下观察带有变量初始值设定项的静态字段”。这有用吗?@Cowan不太有用。它没有解决跨文件的问题。我认为跨文件(即跨不同的类)也会发生同样的情况。在类A的类型初始化期间,将要求类B进行初始化,类B将找到对类A的空引用。现在,在同一类(部分类)的文件中,可能由预处理器来确定它是否失败。因此,如果A引用B.B,则A.A被初始化将碰撞B.B?这是肯定的。第一次引用类型时会调用静态构造函数。这里要注意静态变量初始值设定项和静态构造函数之间的区别。基于静态构造函数的存在/不存在,在类型初始化发生时有不同的规则。请注意,这些代码在运行时并不完全相同: