Сегодня сотрудник спросил меня, как добавить диапазон в коллекцию. У него есть класс, наследующий от Collection<T>
. У этого типа есть свойство только для получения, которое уже содержит некоторые элементы. Он хочет добавить элементы из другой коллекции в коллекцию свойств. Как он может сделать это в стиле C # 3? (Обратите внимание на ограничение свойства get-only, которое предотвращает такие решения, как выполнение Union и переназначение.)
Конечно, foreach с Property. Добавить будет работать. Но List<T>
AddRange в стиле -стайл был бы намного элегантнее.
Достаточно просто написать метод расширения:
public static class CollectionHelpers
{
public static void AddRange<T>(this ICollection<T> destination,
IEnumerable<T> source)
{
foreach (T item in source)
{
destination.Add(item);
}
}
}
Но у меня такое чувство, что я изобретаю велосипед заново. Ничего подобного в System.Linq
или morelinq не нашел .
Плохой дизайн? Просто позвоните и добавьте? Упускаете очевидное?
источник
ICollection<T>
вроде нетAdd
метода. msdn.microsoft.com/en-us/library/ ... ОднакоCollection<T>
есть один.Add(T item)
? Похоже на недоработанный подход, предлагающий возможность добавить один элемент, а затем ожидать, что все вызывающие абоненты будут выполнять итерацию, чтобы добавлять более одного элемента за раз. Ваше утверждение, безусловно, верно,IEnumerable<T>
но я неоднократно разочаровывался в этомICollections
. Я не возражаю с вами, просто высказываюсь.Ответы:
Нет, это кажется вполне разумным. Существует метод
List<T>.
AddRange (), который в основном делает именно это, но требует, чтобы ваша коллекция была конкретнойList<T>
.источник
Попробуйте выполнить приведение к списку в методе расширения перед запуском цикла. Таким образом, вы можете воспользоваться производительностью List.AddRange.
источник
as
Оператор никогда не будет бросать. Еслиdestination
не может быть приведен,list
будет равен нулю, иelse
блок будет выполнен.if (destination is List<T> list)
Поскольку,
.NET4.5
если вам нужен однострочник, вы можете использоватьSystem.Collections.Generic
ForEach.или даже короче как
По производительности он такой же, как и для каждого цикла (синтаксический сахар).
Также не пытайтесь назначить его как
причина
ForEach
недействительна.Изменить: скопировано из комментариев, мнение Липерта о ForEach
источник
ForEach
вроде бы определяется только наList<T>
, а неCollection
?Помните, что каждый
Add
будет проверять емкость коллекции и при необходимости изменять ее размер (медленнее). СAddRange
помощью набора будет установлена емкость, а затем добавлены элементы (быстрее). Этот метод расширения будет очень медленным, но будет работать.источник
Вот немного более продвинутая / готовая к производству версия:
источник
destination
это списокShape
абстрактного класса.source
это списокCircle
унаследованного класса.Все классы библиотеки универсальных коллекций C5 поддерживают этот
AddRange
метод. C5 имеет гораздо более надежный интерфейс , который на самом деле обнажает все особенности его основные реализаций и является интерфейсом , совместимым сSystem.Collections.Generic
ICollection
иIList
интерфейсами, а это означает , чтоC5
коллекции «s может быть легко заменяемыми в качестве основной реализации.источник
Вы можете добавить свой диапазон IEnumerable в список, а затем установить ICollection = в список.
источник
Или вы можете просто сделать расширение ICollection следующим образом:
Его использование аналогично использованию в списке:
источник