Вы можете инициализировать массив следующим образом:
int [ ] arr = { 1, 2, 3, 4, 5 };
но List<T> не позволяет этого:
List<int> list = { 1, 2, 3, 4, 5 };
В чем причина этого?
В конце концов, оба позволяют это:
int [ ] arr = new int [ ] { 1, 2, 3, 4, 5 };
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
Также, почему это невозможно сделать с LinkedList<T> ?:
LinkedList<int> ll = new LinkedList<int>() { 1, 2, 3 };
Обновлять
Спасибо, парни. Только что видел ответы. Я хотел выбрать несколько ответов, но мне это не удалось.
Почему в LinkedList есть метод Add, хотя он явно реализован? Скорее всего, это будет исправлено? Потому что такие проблемы просто как снежный ком превратятся в более крупные, если их не заметить, не так ли?





Я никогда не понимал, что вы не можете использовать инициализацию коллекции с LinkedList (T), но это кажется логичным, поскольку у него нет метода «Добавить», вместо этого есть «AddFirst» и «AddLast». Инициализация коллекции использует метод «Добавить».
Потому что создание массивов встроено в язык, например int [], float [], WhateverClassHere []. Этот синтаксис предназначен для создания массивов, а не для инициализации списков.
В вашем примере вы создаете массив целых чисел. Использование этого синтаксиса для добавления значений в список не должно работать, потому что List не является массивом.
Ваш первый пример - это стандартный синтаксис языка для инициализации массива целых чисел. Левое значение оценивается как int []. Во втором примере вы пытаетесь присвоить int [] объекту List <int>. Оператор присваивания не поддерживает это, поскольку они бывают разных типов. List <int> - это нет, массив типа int. Однако, как вы говорите, есть конструктор для List <int>, который принимает в качестве аргумента int [], а новый синтаксический сахар, добавленный в C# 3.0, позволяет вам удобно использовать {} для добавления членов в коллекцию, определенную конструктор по умолчанию.
Как говорит @Patrik, это не сработает для LinkedList, потому что он не определяет метод Add () как часть своего интерфейса (есть явная реализация ICollection.Add), поэтому синтаксический сахар не будет работать.
Однако для LinkedList есть простой обходной путь.
public class LinkedListWithInit<T> : LinkedList<T>
{
public void Add( T item )
{
((ICollection<T>)this).Add(item);
}
}
LinkedList<int> list = new LinkedListWithInit<int> { 1, 2, 3, 4, 5 };
Хе меня опередил, но лаконично. +1
Я думаю, что это немного странно, поскольку LinkedList (T) действительно имеет метод Add, реализованный для интерфейса ICollection (T). Он реализован явно, поэтому он не является общедоступным, если вы не передадите список в ICollection (T), но я думаю, что он должен быть действительным.
Но нет никакого способа передать его в ICollection между его созданием и попыткой инициализировать его, поэтому явно реализованный интерфейс бесполезен. Я обновил свой ответ, чтобы прояснить это.
Я имел в виду, что считаю, что компилятор должен быть достаточно умен, чтобы найти интерфейс - Добавить. Метод Add для LinkedList (T) никогда не должен был реализовываться явно, но это совершенно другая проблема.
Вероятно, он не просматривает все типы, которые реализуются типом при поиске метода. Мне нужно подумать обо всех вариантах использования, прежде чем я смогу сказать, будет ли это разумным. Я не уверен, почему это не реализовано напрямую; это могло бы показаться разумным.
То, что упускают из виду, беспокоит меня просто потому, что они не собираются исправлять это для обратной совместимости, верно, тогда как библиотеки классов не должны постоянно обновляться к лучшему?
Вот что Спецификация языка C# 3.0 должен сказать по этому поводу:
The following is an example of an object creation expression that includes a collection initializer:
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };The collection object to which a collection initializer is applied must be of a type that implements System.Collections.IEnumerable or a compile-time error occurs. For each specified element in order, the collection initializer invokes an Add method on the target object with the expression list of the element initializer as argument list, applying normal overload resolution for each invocation. Thus, the collection object must contain an applicable Add method for each element initializer.
Это имеет смысл, если подумать. Компилятор гарантирует, что вы работаете с перечислимым типом, который реализует функцию добавления (через которую он выполняет инициализацию).
Если вы хотите использовать инициализатор коллекции с LinkedList и не возражаете против небольшой неэффективности, вы можете сделать это:
var linkedList = new LinkedList<int>(new[] { 1, 2, 3, 4 });
Хитрость заключается в том, чтобы инициализировать массив с помощью инициализатора коллекции, а затем передать его в LinkedList.
Мне это нравится, вы можете объяснить, почему это неэффективно? Это связано с временной сложностью? Или вы просто так говорите, потому что это массив внутри? Извините, опоздание на полтора года.
Небольшая неэффективность возникает из-за необходимости сначала выделить массив (new [] {...}) перед вызовом конструктора LinkedList. Вам нужно будет провести сравнительный анализ, чтобы увидеть, насколько сильно это повлияло на ваш сценарий.
Вы можете создавать экземпляры массивов сложных типов, подобных этому, это не имеет к этому никакого отношения. Вопрос в том, почему синтаксис для создания массива отличается от того, как вы выполняете инициализацию коллекции.