Добавить в коллекцию


коллега спросил меня сегодня, как добавить серии в коллекцию. У него есть класс, который наследует от Collection<T>. Существует свойство get-only этого типа, которое уже содержит некоторые элементы. Он хочет добавить элементы из другой коллекции в коллекцию свойств. Как он может сделать это в C#3-дружественных мода? (обратите внимание на ограничение свойства get-only, которое предотвращает такие решения, как объединение и переназначение.)

конечно, foreach со свойством. Добавить работа. Но 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.

плохой дизайн? Просто Позвоните Добавить? Не хватает очевидного?

6 76

6 ответов:

нет, это кажется вполне разумным. Там есть List<T>.AddRange() метод, который в основном делает именно это, но требует, чтобы ваша коллекция была конкретной List<T>.

попробуйте выполнить приведение к списку в методе расширения перед запуском цикла. Таким образом, вы можете воспользоваться производительностью списка.AddRange.

public static void AddRange<T>(this ICollection<T> destination,
                               IEnumerable<T> source)
{
    List<T> list = destination as List<T>;

    if (list != null)
    {
        list.AddRange(source);
    }
    else
    {
        foreach (T item in source)
        {
            destination.Add(item);
        }
    }
}

помните, что каждый Add будет проверять емкость коллекции и изменять ее размер при необходимости (медленнее). С AddRange, коллекция будет установлена емкость, а затем добавлены элементы (быстрее). Этот метод расширения будет очень медленным, но будет работать.

С .NET4.5 Если вы хотите один-лайнер вы можно использовать System.Collections.Generic ForEach.

source.ForEach(o => destination.Add(o));

или даже короче, как

source.ForEach(destination.Add);

производительность-это то же самое, что и для каждого цикла (синтаксический сахар).

и не попробуйте назначить его как

var x = source.ForEach(destination.Add) 

причина ForEach является недействительным.

The Библиотека Общих Коллекций C5 классы все поддерживают AddRange метод. C5 имеет гораздо более надежный интерфейс, который фактически раскрывает все функции его базовых реализаций и совместим с интерфейсом System.Collections.GenericICollection и IList интерфейсы, что означает C5коллекции могут быть легко заменены в качестве базовой реализации.

вы можете добавить свой диапазон IEnumerable в список, а затем установить ICollection = в список.

        IEnumerable<T> source;

        List<item> list = new List<item>();
        list.AddRange(source);

        ICollection<item> destination = list;