Объединение инициализатора списка и инициализатора объекта

Можно ли объединить инициализатор списка и инициализатор объекта одновременно? Учитывая следующее определение класса:

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 }
Другие вопросы по тегам