Мой вопрос как заголовок выше. Например,
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
но в конце концов он имеет только 1 предмет внутри.
Можем ли мы иметь такой метод items.Add(item)
?
словно List<T>
c#
list
ienumerable
ldsenow
источник
источник
IEnumerable<T>
предназначен только для запросов к коллекциям. Это основа для платформы LINQ. Это всегда абстракция какой - то другой коллекции , такие какCollection<T>
,List<T>
илиArray
. Интерфейс предоставляет толькоGetEnumerator
метод, который возвращает экземпляр,IEnumerator<T>
который позволяет пройти по расширенной коллекции по одному элементу за раз. Методы расширения LINQ ограничены этим интерфейсом.IEnumerable<T>
предназначен только для чтения, поскольку может представлять собой совокупность частей нескольких коллекций.IList<T>
вместоIEnumerable<T>
:IList<T> items = new T[]{new T("msg")}; items.Add(new T("msg2"));
Ответы:
Вы не можете, потому
IEnumerable<T>
что не обязательно представляет коллекцию, в которую могут быть добавлены элементы. На самом деле, это вовсе не обязательно представляет коллекцию! Например:Однако вы можете создать новый
IEnumerable
объект (неопределенного типа), который при перечислении предоставит все элементы старого, а также некоторые ваши собственные. Вы используетеEnumerable.Concat
для этого:Эта не изменит объект массива (в любом случае вы не можете вставлять элементы в массивы). Но он создаст новый объект, который перечислит все элементы в массиве, а затем "Foo". Кроме того, этот новый объект будет отслеживать изменения в массиве (т. Е. Всякий раз, когда вы его перечисляете, вы увидите текущие значения элементов).
источник
Concat
вызывается в цикле повторно; и если это так, у вас все равно есть большие проблемы, потому что каждый раз, когдаConcat
вы получаете, еще один слой перечислителя - так что в конце этого единственный вызовMoveNext
приведет к цепочке вызовов, равной по длине количеству итераций.IEnumerable<T>
C #, включая перегрузку,operator+
какConcat
(кстати, вы знаете, что в VB вы можете индексировать,IEnumerable
как если бы это был массив - он используетElementAt
под капотом): connect.microsoft.com / VisualStudio / обратная связь /… . Если мы получим еще две перегрузки для того,Concat
чтобы взять один элемент как слева, так и справа, это приведет к сокращению набора текстаxs +=x
- так что, пошлите в Mads (Torgersen), чтобы расставить приоритеты в C # 5.0 :)Тип
IEnumerable<T>
не поддерживает такие операции. НазначениеIEnumerable<T>
интерфейса - позволить потребителю просматривать содержимое коллекции. Не изменять значения.Когда вы выполняете такие операции, как .ToList (). Add (), вы создаете новый
List<T>
и добавляете значение в этот список. Это не имеет никакого отношения к первоначальному списку.Что вы можете сделать, это использовать метод Add extension, чтобы создать новый
IEnumerable<T>
с добавленной стоимостью.Даже в этом случае он не изменит оригинальный
IEnumerable<T>
объект. Это можно проверить, сохранив ссылку на него. НапримерПосле этого набора операций переменная temp по-прежнему будет ссылаться только на перечислимое значение с одним элементом «foo» в наборе значений, в то время как элементы будут ссылаться на другое перечисляемое значение со значениями «foo» и «bar».
РЕДАКТИРОВАТЬ
Я постоянно забываю, что Add не является типичным методом расширения,
IEnumerable<T>
потому что это один из первых, который я в итоге определил. Вотисточник
Concat
:)Add
, потому чтоAdd
практически любой другой тип .NET (не только коллекции) изменяет коллекцию на месте. Может бытьWith
? Или это может быть просто очередная перегрузкаConcat
.Concat
перегрузка, вероятно, будет лучшим выбором, посколькуAdd
обычно подразумевает изменчивость.return e.Concat(Enumerable.Repeat(value,1));
?Рассматривали ли вы использование интерфейсов
ICollection<T>
илиIList<T>
вместо них, они существуют по той самой причине, что вы хотите иметьAdd
метод наIEnumerable<T>
.IEnumerable<T>
используется, чтобы «пометить» тип как ... ну, перечисляемый или просто последовательность элементов, не обязательно делая какие-либо гарантии того, поддерживает ли реальный базовый объект добавление / удаление элементов. Также помните, что эти интерфейсы реализованы,IEnumerable<T>
так что вы получаете все методы расширений, которые вы получаетеIEnumerable<T>
также.источник
Несколько коротких, приятных методов расширения
IEnumerable
иIEnumerable<T>
сделайте это для меня:Элегантный (ну, за исключением неуниверсальных версий). Жаль, что эти методы не в BCL.
источник
ToString()
ним исключение , так как это фиксирует больше деталей об ошибках. Я предполагаю, что вы неinclude System.Linq;
в верхней части вашего файла, но кто знает? Попробуйте выяснить это самостоятельно, создайте минимальный прототип, который показывает ту же ошибку, если вы не можете, а затем попросите помощи в вопросе.В .net Core есть метод,
Enumerable.Append
который делает именно это.Исходный код метода доступен на GitHub. .... Реализация (более сложная, чем предложения в других ответах) стоит посмотреть :).
источник
Нет, IEnumerable не поддерживает добавление элементов к нему.
Вы «альтернатива» это:
источник
Чтобы добавить второе сообщение, вам нужно -
источник
Вы не только не можете добавлять элементы, как вы заявляете, но если вы добавляете элемент в
List<T>
(или почти в любую другую не доступную только для чтения коллекцию), для которой у вас есть существующий перечислитель, перечислитель становится недействительным (InvalidOperationException
с тех пор включается ).Если вы агрегируете результаты из какого-либо типа запроса данных, вы можете использовать
Concat
метод расширения:Редактировать: я изначально использовал
Union
расширение в примере, что не совсем правильно. Мое приложение широко использует его, чтобы убедиться, что перекрывающиеся запросы не дублируют результаты.источник
Я просто пришел сюда, чтобы сказать, что, кроме
Enumerable.Concat
метода расширения, кажется, есть еще один метод, названныйEnumerable.Append
в .NET Core 1.1.1. Последнее позволяет объединить один элемент в существующую последовательность. Так что ответ Аамола можно записать так:Тем не менее, обратите внимание, что эта функция не изменит последовательность ввода, она просто вернет оболочку, которая соединит данную последовательность и добавленный элемент вместе.
источник
Другие уже дали отличные объяснения относительно того, почему вы не можете (и не должны!) Добавлять элементы в
IEnumerable
. Я только добавлю, что если вы хотите продолжить кодирование в интерфейсе, представляющем коллекцию, и хотите добавить метод, вам следует написать кодICollection
илиIList
. В качестве дополнительного бонуса, эти интерфейсы реализуютIEnumerable
.источник
ты можешь сделать это.
источник
Самый простой способ сделать это просто
Затем вы можете вернуть список как IEnumerable также потому, что он реализует интерфейс IEnumerable
источник
Если вы создаете свой объект как
IEnumerable<int> Ones = new List<int>();
Тогда вы можете сделать((List<int>)Ones).Add(1);
источник
Конечно, вы можете (я оставляю ваш T-бизнес в стороне):
источник