Инициализация коллекции

Вы можете инициализировать массив следующим образом:

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, хотя он явно реализован? Скорее всего, это будет исправлено? Потому что такие проблемы просто как снежный ком превратятся в более крупные, если их не заметить, не так ли?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
0
15 587
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Я никогда не понимал, что вы не можете использовать инициализацию коллекции с LinkedList (T), но это кажется логичным, поскольку у него нет метода «Добавить», вместо этого есть «AddFirst» и «AddLast». Инициализация коллекции использует метод «Добавить».

Потому что создание массивов встроено в язык, например int [], float [], WhateverClassHere []. Этот синтаксис предназначен для создания массивов, а не для инициализации списков.

В вашем примере вы создаете массив целых чисел. Использование этого синтаксиса для добавления значений в список не должно работать, потому что List не является массивом.

Вы можете создавать экземпляры массивов сложных типов, подобных этому, это не имеет к этому никакого отношения. Вопрос в том, почему синтаксис для создания массива отличается от того, как вы выполняете инициализацию коллекции.

Patrik Hägne 06.01.2009 00:47
Ответ принят как подходящий

Ваш первый пример - это стандартный синтаксис языка для инициализации массива целых чисел. Левое значение оценивается как 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

Kev 06.01.2009 00:50

Я думаю, что это немного странно, поскольку LinkedList (T) действительно имеет метод Add, реализованный для интерфейса ICollection (T). Он реализован явно, поэтому он не является общедоступным, если вы не передадите список в ICollection (T), но я думаю, что он должен быть действительным.

Patrik Hägne 06.01.2009 00:53

Но нет никакого способа передать его в ICollection между его созданием и попыткой инициализировать его, поэтому явно реализованный интерфейс бесполезен. Я обновил свой ответ, чтобы прояснить это.

tvanfosson 06.01.2009 01:03

Я имел в виду, что считаю, что компилятор должен быть достаточно умен, чтобы найти интерфейс - Добавить. Метод Add для LinkedList (T) никогда не должен был реализовываться явно, но это совершенно другая проблема.

Patrik Hägne 06.01.2009 01:09

Вероятно, он не просматривает все типы, которые реализуются типом при поиске метода. Мне нужно подумать обо всех вариантах использования, прежде чем я смогу сказать, будет ли это разумным. Я не уверен, почему это не реализовано напрямую; это могло бы показаться разумным.

tvanfosson 06.01.2009 05:08

То, что упускают из виду, беспокоит меня просто потому, что они не собираются исправлять это для обратной совместимости, верно, тогда как библиотеки классов не должны постоянно обновляться к лучшему?

Joan Venge 06.01.2009 05:12

Вот что Спецификация языка 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.

Мне это нравится, вы можете объяснить, почему это неэффективно? Это связано с временной сложностью? Или вы просто так говорите, потому что это массив внутри? Извините, опоздание на полтора года.

jah 29.10.2020 01:53

Небольшая неэффективность возникает из-за необходимости сначала выделить массив (new [] {...}) перед вызовом конструктора LinkedList. Вам нужно будет провести сравнительный анализ, чтобы увидеть, насколько сильно это повлияло на ваш сценарий.

Samuel Jack 11.01.2021 23:24

Другие вопросы по теме