Почему 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

Эмильен Матье
источник