它将始终正常运行吗?
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()
我还有其他需要担心的事情吗?
答案 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);