初始化的顺序是什么?

时间:2019-02-21 08:26:24

标签: c#

它将始终正常运行吗?

public class Test
{
    public static List<int> a = new List<int>{1,2,3};

    public static List<int> b = new List<int>(a);
}

因为我切换了它们

public class Test
{
    public static List<int> b = new List<int>(a);

    public static List<int> a = new List<int>{1,2,3};
}

然后我收到

  

用户代码中的异常:

     

System.ArgumentNullException:值不能为null。   参数名称:集合      在System.Collections.Generic.List 1..ctor(IEnumerable 1集合中)      在.Test..cctor()

我还有其他需要担心的事情吗?

2 个答案:

答案 0 :(得分:1)

如果需要确定性初始化,请使用静态构造函数:

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

private static Test()
{
  a = new List<int>{1,2,3};
  b = new List<int>(a);
}

C#/ CLR规范确保了执行字段初始化程序的顺序,但是正如您所注意到的,如果您弄乱了类中字段的顺序,则在运行时时事情会崩溃。考虑到切换类中字段的顺序是多么容易,所以无论合同行为如何,这都是一个坏主意。

所以我的建议是:如果字段初始化程序不依赖于其他字段,请保留它们。如果这样做,则将初始化放入构造函数中,该构造函数的顺序非常明确。

规范中的相关报价:

  

如果类包含带有初始化程序的任何静态字段,则这些初始化程序将在执行静态构造函数之前立即按文本顺序执行(第17.4.5节)。

因此,您可以合同方式依赖文本顺序,但我仍然建议您反对它。这太容易破坏了,人们通常不认为类代码文件中成员的顺序很重要。如果您遇到编译错误,那很好,但是您没有-如果您很幸运,您会遇到运行时错误。如果不是,那么您将陷入与更改无关的“不可能”情况(对吗?)。

答案 1 :(得分:0)

是的,正如您正确观察到的那样,顺序必须保持如下所示,因为成员字段将按照顺序进行初始化

public static List<int> a = new List<int>{1,2,3};
public static List<int> b = new List<int>(a);