Подтвердить что ты не робот

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

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

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 };

Это по дизайну или это просто ошибка или недостающая особенность компилятора С#?

4b9b3361

Ответ 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 }