Сегодня я с удивлением обнаружил, что на C # я могу:
List<int> a = new List<int> { 1, 2, 3 };
Почему я могу это сделать? Какой конструктор называется? Как я могу сделать это с моими собственными классами? Я знаю, что это способ инициализации массивов, но массивы - это языковые элементы, а списки - простые объекты ...
c#
.net
list
initialization
Игнасио Солер Гарсия
источник
источник
{ { "key1", "value1"}, { "key2", "value2"} }
List<int>
на самом деле является только массивом. Ненавижу команду C # за то, что они не называют этоArrayList<T>
так очевидным и естественным.Ответы:
Это часть синтаксиса инициализатора коллекции в .NET. Вы можете использовать этот синтаксис в любой создаваемой коллекции, если:
Реализует
IEnumerable
(желательноIEnumerable<T>
)У него есть метод с именем
Add(...)
Что происходит, вызывается конструктор по умолчанию, а затем
Add(...)
вызывается для каждого члена инициализатора.Таким образом, эти два блока примерно идентичны:
И
Вы можете вызвать альтернативный конструктор, если хотите, например, чтобы предотвратить завышение размера во
List<T>
время выращивания и т. Д .:Обратите внимание, что
Add()
метод не должен принимать один элемент, напримерAdd()
метод дляDictionary<TKey, TValue>
принимает два элемента:Примерно идентичен:
Итак, чтобы добавить это в свой собственный класс, все, что вам нужно сделать, как уже упоминалось, - это реализовать
IEnumerable
(опять же, предпочтительноIEnumerable<T>
) и создать один или несколькоAdd()
методов:Затем вы можете использовать его так же, как коллекции BCL:
(Для получения дополнительной информации см. MSDN )
источник
List<int> temp = new List<int>(); temp.Add(1); ... List<int> a = temp;
То есть,a
переменная не инициализирована , пока после того, как все добавляет называются. В противном случае было бы законным делать что-то вродеList<int> a = new List<int>() { a.Count, a.Count, a.Count };
безумия.List<int> a; a = new List<int>() { a.Count };
иList<int> a = new List<int>() { a.Count };
T x = y;
это то же самое, что иT x; x = y;
, Этот факт может привести к некоторым странным ситуациям. Например,int x = M(out x) + x;
это совершенно законно, потому чтоint x; x = M(out x) + x;
это законно.IEnumerable<T>
; неуниверсальногоIEnumerable
достаточно, чтобы разрешить использование синтаксиса инициализатора коллекции.using (var x = new Something{ 1, 2 })
не удалит объект, если один изAdd
вызовов не удастся.Это так называемый синтаксический сахар .
List<T>
- это «простой» класс, но компилятор уделяет ему особое внимание, чтобы облегчить вам жизнь.Это так называемый инициализатор коллекции . Вам нужно реализовать
IEnumerable<T>
иAdd
метод.источник
Согласно спецификации C # версии 3.0 «Объект коллекции, к которому применяется инициализатор коллекции, должен иметь тип, реализующий System.Collections.Generic.ICollection ровно для одного T.»
Однако на момент написания эта информация кажется неточной; см. пояснение Эрика Липперта в комментариях ниже.
источник
Он работает благодаря инициализаторам коллекций, которые в основном требуют, чтобы коллекция реализовывала метод Add и который сделает всю работу за вас.
источник
Еще одна интересная особенность инициализаторов коллекций заключается в том, что у вас может быть несколько перегрузок
Add
метода, и вы можете вызывать их все в одном инициализаторе! Например, это работает:Вызывает правильные перегрузки. Кроме того, он ищет только метод с именем
Add
, возвращаемый тип может быть любым.источник
Синтаксис, подобный массиву, превращается в серию
Add()
вызовов.Чтобы увидеть это на гораздо более интересном примере, рассмотрим следующий код, в котором я делаю две интересные вещи, которые сначала кажутся незаконными в C #: 1) установка свойства readonly, 2) установка списка с массивом, таким как инициализатор.
Этот код будет работать отлично, хотя 1) MyList доступен только для чтения и 2) я установил список с инициализатором массива.
Причина, по которой это работает, заключается в том, что в коде, который является частью инициализатора объекта, компилятор всегда превращает любой
{}
подобный синтаксис в сериюAdd()
вызовов, которые совершенно допустимы даже в поле только для чтения.источник