Чому 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
Вони можуть бути реалізовані як методи розширення, таким чином, реалізації інтерфейсу не доведеться їх реалізовувати. Чому вони не?
Том Пажурек

15
Це не має сенсу. Інтерфейс абстрагує реалізацію, так що може бути декілька реалізацій однакових основних функцій; немає жодної причини, чому функції повинні бути опущені з інтерфейсу, оскільки "реалізація важка". Без таких методів, як "AddRange" на інтерфейсі, немає гарантії, що базовий об'єкт їх підтримує, і в цей момент ви змушені або реалізувати неоптимальне розширення, або перемогти мету використання інтерфейсу, роблячи небезпечні припущення, намагаючись кинути до певного реалізовуючого класу. Знижені інтерфейси надмірно використовуються.
Трійко

3
Повинен бути інтерфейс IRangeList, що підтримує масові операції, реалізований лише на деяких колекціях, які всередині матимуть оптимальне виконання.
теж

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.