什么是C#中的静态变量初始化顺序? [英] What is the static variable initialization order in C#?

查看:381
本文介绍了什么是C#中的静态变量初始化顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<一个href=\"http://msdn.microsoft.com/en-us/library/ms597484.aspx#exampleToggle\">DependencyProperty.AddOwner MSDN页面提供了一个示例有两个班,静态成员,一个类的成员取决于其他类的初始化的成员。我觉得MSDN是错的 - 静态变量的初始化顺序是C#就像它是不可靠的在C ++ 或其他地方。我可能是错的,因为WPF库本身是用这种方式,它工作得很好。我在想什么?如何C#编译器可能知道安全初始化顺序?

DependencyProperty.AddOwner MSDN page offers an example with two classes with static members, and the member of one class depends on the member of the other class for initialization. I think MSDN is wrong - the initialization order of static variables is unreliable in C# just like it is in C++ or anywhere else. I'm probably wrong because the WPF library itself is written that way and it works just fine. What am I missing? How can C# compiler possibly know the safe initialization order?

推荐答案

这是罚款一类依赖于其他类型的初始化,只要你不要在一个周期结束了。

It's fine for one type to depend on another type being initialized, so long as you don't end up in a cycle.

基本上,这是好的:

public class Child
{
    static Child() {} // Added static constructor for extra predictability
    public static readonly int X = 10;
}

public class Parent
{
    static Parent() {} // Added static constructor for extra predictability
    public static readonly int Y = Child.X;
}

结果被明确定义。 儿童的静态变量初始化是按规范第10.5.5.1到第一个访问任何静态字段在课前执行。

The result is well-defined. Child's static variable initializers are executed prior to the first access to any static field in the class, as per section 10.5.5.1 of the spec.

这是没有,但:

public class Child
{
    public static readonly int Nasty = Parent.Y;
    public static readonly int X = 10;
}

public class Parent
{
    public static readonly int Y = Child.X;
}

在后一种情况下,你的或者的结束了 Child.Nasty = 0 Parent.Y = 10 Child.X = 10 Child.Nasty = 0 Parent.Y = 0 Child.X = 10 取决于哪个类第一次访问。

In this latter case, you either end up with Child.Nasty=0, Parent.Y=10, Child.X=10 or Child.Nasty=0, Parent.Y=0, Child.X=10 depending on which class is accessed first.

访问 Parent.Y第一个将开始初始化第一。 儿童的初始化将意识到需要初始化,但CLR知道它已经被初始化,所以进行不分,导致第一组数字 - 因为 Child.X 最终用于 Parent.Y

Accessing Parent.Y first will start initializing Parent first. The initialization of Child will realise that Parent needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the first set of numbers - because Child.X ends up being initialized before its value is used for Parent.Y.

访问 Child.Nasty 将开始初始化儿童第一,然后将开始初始化父的初始化将意识到儿童需要初始化,但CLR知道它已经被初始化,所以进行不分,导致第二组数字。

Accessing Child.Nasty will start initializing Child first, which will then start to initialize Parent. The initialization of Parent will realise that Child needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the second set of numbers.

别这样做。


编辑:好了,更详细的解释,如许

Okay, more detailed explanation, as promised.

当一个类型初始化?

如果一个类型有一个静态构造函数的,它只会被初始化
当它第一次使用(或者当静态成员被引用,或
当创建一个实例)。如果是的的有一个静态
构造,也可以进行初始化早期的版本。在理论上也有可能
在稍后初始化;理论上你就可以调用构造函数或
没有静态变量的静态方法初始化 - 但
它的必须的静态变量引用之前初始化。

If a type has a static constructor, it will only be initialized when it's first used (either when a static member is referenced, or when an instance is created). If it doesn't have a static constructor, it can be initialized earler. In theory it could also be initialized later; you could theoretically call a constructor or a static method without the static variables being initialized - but it must be initialized before static variables are referenced.

初始化过程中会发生什么?

首先静态变量获得其默认值(0,空
等等)。

First all static variables receive their default values (0, null etc).

然后该类型中的静态变量在文本被初始化
订购。如果一个静态变量初始化前pression要求
另一种类型的被初始化,则该其他类型将是
被赋予变量的值之前完全初始化 -
除非的该第二类型的已被初始化(由于
循环依赖)。本质上,一个类型可以是:

Then the static variables of the type are initialized in textual order. If the initializer expression for a static variable requires another type to be initialized, then that other type will be completely initialized before the variable's value is assigned - unless that second type is already being initialized (due to a cyclic dependency). Essentially, a type is either:


  • 已经初始化

  • 在此刻被初始化

  • 未初始化

如果该类型没有初始化初始化时才会触发。
这意味着,当有循环依赖,有可能
其初始值面前,观察一个静态变量的值的
分配
的。这就是我的儿童 / 示例所示。

Initialization is only triggered if the type is not initialized. This means that when there are cyclic dependencies, it is possible to observe a static variable's value before its initial value has been assigned. That's what my Child/Parent example shows.

在所有静态变量初始化已执行,静
构造函数执行。

After all the static variable initializers have executed, the static constructor executes.

查看C#规范的10.12节关于这一切的更多细节。

See section 10.12 of the C# spec for more details on all of this.


应广大用户要求,这里是我原来的答复时,我认为问题是关于静态变量的初始化顺序的类中的的:

By popular demand, here was my original answer when I thought the question was about the initialization order of static variables within a class:

静态变量初始化在文本顺序,按照在C#规范第10.5.5.1:

Static variables are initialized in textual order, as per section 10.5.5.1 of the C# spec:

的静态字段变量初始化
  一类的对应的一个序列
  这是在执行任务
  在它们出现在文字顺序
  类的声明。

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration.

注意局部类型作出有之类的没有一个规范的文本秩序这一棘手。

Note that partial types make this trickier as there's no one canonical "textual order" of the class.

这篇关于什么是C#中的静态变量初始化顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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