关于c#:组合List初始化器和对象初始化器

Combining List initializer and object initializer

是否可以同时组合列表初始值设定项和对象初始值设定项?给定以下类定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyList : List<int>
{
    public string Text { get; set; }
}

// we can do this
var obj1 = new MyList() { Text="Hello" };

// we can also do that
var obj2 = new MyList() { 1, 2, 3 };

// but this one doesn't compile
//var obj3 = new MyList() { Text="Hello", 1, 2, 3 };

这是由设计造成的,还是仅仅是C编译器的一个缺陷或缺失的特性?


不,从C规范第7.6.10节的定义来看,object-or-collection-initializer表达式要么是object-initializer要么是collection-initializer

object-initializer由多个member-initializer组成,每个initializer = initializer-value的形式,而collection-initializer由多个element-initializer组成,每个non-assigment-expression的形式。

所以它看起来像是设计出来的——可能是为了简单。老实说,我从来没想过要这么做。(我通常不会从List开始——我会改为作曲。)我真的不想看到:

1
var obj3 = new MyList { 1, 2, Text ="Hello", 3, 4 };

编辑:如果你真的,真的想启用这个,你可以把它放在类中:

1
2
3
4
5
class MyList : List<int>
{
    public string Text { get; set; }
    public MyList Values { get { return this; } }
}

这时你可以写:

1
var obj3 = new MyList { Text ="Hello", Values = { 1, 2, 3, 4 } };


不,这不是虫子。这是语言的设计。

当你写作时

1
var obj1 = new MyList() { Text="Hello" };

编译器有效地将其翻译为

1
2
3
MyList temp = new MyList();
temp.Text ="Hello";
MyList obj = temp;

当你写作时

1
var obj2 = new MyList() { 1, 2, 3 };

编译器有效地将其翻译为

1
2
3
4
5
MyList temp = new MyList();
temp.Add(1);
temp.Add(2);
temp.Add(3);
MyList obj2 = temp;

注意,在第一种情况下,您使用的是对象初始值设定项,而在第二种情况下,您使用的是集合初始值设定项。没有对象和集合初始化器这样的东西。您正在初始化对象的属性,或者正在初始化集合。你不能两者兼得,这是按设计的。

另外,你不应该从List中得到。请参见:继承list以实现集合是一个坏主意?


如果要获得类似于此功能的内容,请考虑生成一个构造函数参数:

1
var x = new CustomList("Hello World") { 1, 2, 3 }