Объединение инициализатора списка и инициализатора объекта
Можно ли одновременно объединить инициализатор списка и инициализатор объекта?
Учитывая следующее определение класса:
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 };
Это по дизайну или это просто ошибка или недостающая особенность компилятора С#?
Ответы
Ответ 1
Нет, глядя на определения из раздела 7.6.10 спецификации С#, выражение object-or-collection-initializer
является либо object-initializer
, либо collection-initializer
.
An object-initializer
состоит из нескольких member-initializer
s, каждый из которых имеет вид initializer = initializer-value
, тогда как a collection-initializer
состоит из нескольких element-initializer
s, каждый из которых является non-assigment-expression
.
Таким образом, он выглядит как по дизайну - возможно, для простоты. Я не могу сказать, что когда-либо хотел сделать это, если честно. (Обычно я бы не начинал с List<int>
для начала - я бы скомплектовал его.) Мне было бы очень жаль видеть:
var obj3 = new MyList { 1, 2, Text = "Hello", 3, 4 };
EDIT: Если вы действительно хотите включить это, вы можете поместить это в класс:
class MyList : List<int>
{
public string Text { get; set; }
public MyList Values { get { return this; } }
}
в который вы могли бы написать:
var obj3 = new MyList { Text = "Hello", Values = { 1, 2, 3, 4 } };
Ответ 2
Нет, это не ошибка. Это по дизайну языка.
Когда вы пишете
var obj1 = new MyList() { Text="Hello" };
это эффективно преобразуется компилятором в
MyList temp = new MyList();
temp.Text = "Hello";
MyList obj = temp;
Когда вы пишете
var obj2 = new MyList() { 1, 2, 3 };
это эффективно преобразуется компилятором в
MyList temp = new MyList();
temp.Add(1);
temp.Add(2);
temp.Add(3);
MyList obj2 = temp;
Обратите внимание, что в первом случае вы используете инициализатор объекта, но во втором случае вы используете инициализатор коллекции. Нет такой вещи как объект-и-сборник intializer. Вы либо инициализируете свойства своего объекта, либо инициализируете коллекцию. Вы не можете обойти оба, это по дизайну.
Кроме того, вы не должны извлекаться из List<T>
. См. Наследование списка <T> для создания коллекций плохая идея?
Ответ 3
Если вы хотите получить что-то вроде этой функции, подумайте о создании аргумента конструктора:
var x = new CustomList("Hello World") { 1, 2, 3 }