Объединение инициализатора списка и инициализатора объекта
Можно ли объединить инициализатор списка и инициализатор объекта одновременно? Учитывая следующее определение класса:
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#?
3 ответа
Нет, глядя на определения из раздела 7.6.10 спецификации C#, object-or-collection-initializer
выражение либо object-initializer
или collection-initializer
,
object-initializer
состоит из нескольких member-initializer
с, каждый из которых имеет форму initializer = initializer-value
тогда как collection-initializer
состоит из нескольких element-initializer
с, каждый из которых является non-assigment-expression
,
Таким образом, похоже, что это по замыслу - возможно, ради простоты. Я не могу сказать, что когда-либо хотел сделать это, если честно. (Я обычно не получаю от List<int>
для начала - я бы написал это вместо этого.) Мне бы очень не хотелось видеть:
var obj3 = new MyList { 1, 2, Text = "Hello", 3, 4 };
РЕДАКТИРОВАТЬ: Если вы действительно, действительно хотите включить это, вы можете поместить это в классе:
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 } };
Нет, это не ошибка. Это по замыслу языка.
Когда ты пишешь
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;
Обратите внимание, что в первом случае вы используете инициализатор объекта, а во втором - инициализатор коллекции. Нет такого понятия, как инициализатор объекта и коллекции. Вы либо инициализируете свойства вашего объекта, либо инициализируете коллекцию. Вы не можете сделать оба, это по замыслу.
Кроме того, вы не должны выводить из List<T>
, Смотрите: Наследование List
Если вы хотите получить что-то вроде этой функциональности, рассмотрите возможность создания аргумента конструктора:
var x = new CustomList("Hello World") { 1, 2, 3 }