在使用List作为属性初始化类时,我目睹了一些奇怪的事情。这样做时
var stuff = new Stuff(){list = {1, 2, 3} };
它编译,崩溃说列表为空。所以,将它添加到Stuff的构造函数中:
public Stuff(){
list = new List<int>();
}
列表现在已初始化为包含{1, 2, 3}
,这似乎有些道理。但是,然后将构造函数更改为
public Stuff(){
list = new List<int>(){1, 2, 3};
}
并像这样初始化
var stuff = new Stuff(){list = {4, 5, 6} };
列表初始化为包含{1, 2, 3, 4, 5, 6}
让我感到困惑。
这似乎不应该编译,或者不应该这样做。到底发生了什么?
答案 0 :(得分:3)
这似乎不应该编译,或者不应该这样做。到底发生了什么?
集合初始化程序通过在传入初始化程序的每个项目上调用.Add
方法来工作。这个将添加到您在构造函数中预先填充的项目中。
the documentation for Collection Initializers中解释了这一点:
Collection初始化程序允许您在初始化实现IEnumerable的集合类时指定一个或多个元素初始值设定项。元素初始值设定项可以是简单值,表达式或对象初始值设定项。通过使用集合初始值设定项,您不必在源代码中指定对类的Add方法的多个调用;编译器添加了调用。
这意味着编译器会将您的第二个调用转换为类似于:
的内容var temp = new Stuff();
temp.list.Add(4);
temp.list.Add(5);
temp.list.Add(6);
Stuff stuff = temp;
正如您所看到的,stuff
变量将正常调用构造函数(添加1
,2
和3
),然后添加其他项,结果在你所看到的。
答案 1 :(得分:3)
您正在使用collection initializer初始化list
。这种方式可以在文档中给出:
集合初始值设定项允许您指定一个或多个元素 初始化实现的集合类时的初始化程序
IEnumerable
。元素初始值设定项可以是一个简单的值,即 表达式或对象初始值设定项。通过使用集合初始化程序 您不必指定多次调用Add
方法 您的源代码中的类;编译器添加了调用。
换句话说,这个:
var stuff = new Stuff(){list = {1, 2, 3} };
是写这个的简写方式:
var temp = new Stuff();
temp.list.Add(1);
temp.list.Add(2);
temp.list.Add(3);
stuff = temp;
如果NullReferenceException
为list
以及它如何附加到列表中的现有项目(如果有),则很容易看出这会导致null
。