Почему массив реализует IList?

См. определение класса System.Array

public abstract class Array : IList, ...

Теоретически, я должен уметь писать этот бит и быть счастливым

int[] list = new int[] {};
IList iList = (IList)list;

Я также должен иметь возможность вызывать любой метод из iList

 ilist.Add(1); //exception here

Мой вопрос не в том, почему я получаю исключение, а скорее , почему Array реализует IList?

Ответ 1

Поскольку массив обеспечивает быстрый доступ по индексу, а IList/IList<T> - это единственные интерфейсы коллекции, которые поддерживают это. Поэтому, возможно, ваш реальный вопрос: "Почему нет интерфейса для постоянных коллекций с индексаторами?" И к этому у меня нет ответа.

В коллекциях нет интерфейсов readonly. И я пропускаю те, которые даже больше, чем постоянный размер с интерфейсом индексаторов.

IMO должно быть еще несколько (универсальных) интерфейсов коллекции в зависимости от особенностей коллекции. И имена должны были быть разными, List для чего-то с индексом действительно глупо ИМО.

  • Просто перечисление IEnumerable<T>
  • Только для чтения, но нет индексатора (.Count,.Contains,...)
  • Изменяется размер, но нет индексатора, то есть устанавливает (Add, Remove,...) current ICollection<T>
  • Readonly с индексом (indexer, indexof,...)
  • Постоянный размер с индексом (индекс с установщиком)
  • Переменный размер с индексом (Insert,...) current IList<T>

Я думаю, что текущие интерфейсы коллекции плохие. Но поскольку у них есть свойства, указывающие вам, какие методы действительны (и это часть контракта этих методов), он не нарушает принцип подстановки.

Ответ 2

В разделе примечаний документации для IList говорится

IList является потомком Интерфейс ICollection и является базовым интерфейс всех не общих списков. реализации IList делятся на три категории: только для чтения, фиксированный размер и переменной размер. Только для чтения IList не могут быть изменены. Фиксированный размер IList не позволяет добавлять или удалять элементов, но это позволяет модификация существующих элементов. Илист с переменным размером позволяет добавление, удаление и модификация элементы.

Очевидно, что массивы попадают в категорию фиксированного размера, поэтому по определению интерфейса это имеет смысл.

Ответ 3

Поскольку не все IList являются изменяемыми (см. IList.IsFixedSize и IList.IsReadOnly), а массивы, безусловно, ведут себя как списки фиксированного размера.

Если ваш вопрос действительно "почему он реализует не общий интерфейс", тогда ответ заключается в том, что они были вокруг до появления дженериков.

Ответ 4

Это наследие, которое мы имеем со времен, когда не было ясно, как обращаться с коллекциями только для чтения, и является ли Array доступным только для чтения. В интерфейсе IList есть флаги IsFixedSize и IsReadOnly. Флаг IsReadOnly означает, что коллекция не может быть изменена вообще, а IsFixedSize означает, что коллекция разрешает изменение, но не добавление или удаление элементов.

Во времена .Net 4.5 было ясно, что некоторые "промежуточные" интерфейсы необходимы для работы с коллекциями только для чтения, поэтому были введены IReadOnlyCollection<T> и IReadOnlyList<T>.

Вот отличное сообщение в блоге с подробным описанием: Коллекции только для чтения в .NET

Ответ 5

Определение интерфейса IList - "Представляет собой не общий набор объектов, к которым можно индивидуально обращаться по индексу". Массив полностью удовлетворяет этому определению, поэтому должен реализовывать интерфейс. Исключение при вызове метода Add() - это "System.NotSupportedException: коллекция имеет фиксированный размер" и возникла потому, что массив не может динамически увеличить свою емкость. Его емкость определяется при создании объекта массива.