Почему IList не поддерживает AddRange


89

List.AddRange()существует, но IList.AddRange()не существует.
Это кажется мне странным. В чем причина этого?

Ответы:


68

Потому что интерфейс должен быть простым в реализации и не содержать «все, кроме кухни». Если вы добавляете, AddRangeвы должны добавить InsertRangeи RemoveRange(для симметрии). Лучше спросить, почему нет методов расширения для IList<T>интерфейса, аналогичного IEnumerable<T>интерфейсу. (методы расширения для на месте Sort, BinarySearch... было бы полезно)


35
@ShdNx Их нетривиально реализовать с точки зрения производительности. «Внутренний» AddRange/RemoveRange/InsertRangeможет работать непосредственно с «внутренней» коллекцией и оптимизировать Capacityуправление и использовать такие методы, как Array.Copyперемещение блоков данных. Метод расширения RemoveRange, вероятно, будет на порядок медленнее, чемList.RemoveRange
— xanatos

2
Жаль, что не было (и до сих пор нет) способа для объявления интерфейса (например IFoo) указать «вспомогательное» пространство имен (например MyAssembly), так что если класс заявляет о реализации, IFooно не имеет метода int Bar(String), компилятор автоматически генерировать метод int IFoo.Bar(String p1) {return MyAssembly.ClassHelpers.IFoo.Bar(this, p1);} Если бы такая функция существовала, интерфейсы могли бы включать больше методов, например, AddRangeкоторые могли бы быть реализованы в терминах базового поведения, но которые некоторые реализации могли бы оптимизировать.
— supercat

1
Они могут быть реализованы как методы расширения, чтобы реализация интерфейса не реализовывала их. Почему нет?
— Tom Pažourek 05

15
Это не имеет никакого смысла. Интерфейс абстрагирует реализацию, поэтому может быть несколько реализаций одних и тех же основных функций; нет причин, по которым функции должны быть исключены из интерфейса, потому что «реализация сложна». Без таких методов, как «AddRange» в интерфейсе, нет гарантии, что базовый объект поддерживает их, и в этот момент вы вынуждены либо реализовать неоптимальное расширение, либо отказаться от цели использования интерфейса, сделав опасные предположения, пытаясь приведение к конкретному классу реализации. Упрощенные интерфейсы используются слишком часто.
— Трийнко

3
Должен быть интерфейс IRangeList, поддерживающий массовые операции, реализованный только в некоторых коллекциях, которые внутренне будут иметь оптимальную реализацию.
— too

8

Для тех, кто хочет иметь методы расширения для "AddRange", "Sort", ... в IList,

Ниже приведен AddRangeметод расширения:

 public static void AddRange<T>(this IList<T> source, IEnumerable<T> newList)
 {
     if (source == null)
     {
        throw new ArgumentNullException(nameof(source));
     }

     if (newList == null)
     {
        throw new ArgumentNullException(nameof(newList));
     }

     if (source is List<T> concreteList)
     {
        concreteList.AddRange(newList);
        return;
     }

     foreach (var element in newList)
     {
        source.Add(element);
     }
}

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

Некоторые методы медленнее, чем List, но они делают свою работу.

Вот GitHub, чтобы их заинтересовать:

Репозиторий IListExtension

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.