列表属性的初始化程序语法

时间:2013-10-30 21:55:57

标签: c#

在使用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}让我感到困惑。

这似乎不应该编译,或者不应该这样做。到底发生了什么?

2 个答案:

答案 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变量将正常调用构造函数(添加123),然后添加其他项,结果在你所看到的。

答案 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;

如果NullReferenceExceptionlist以及它如何附加到列表中的现有项目(如果有),则很容易看出这会导致null