Почему массив реализует IList? - PullRequest
133 голосов
/ 11 мая 2011

См. Определение System.Array class

public abstract class Array : IList, ...

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

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

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

 ilist.Add(1); //exception here

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

Ответы [ 5 ]

89 голосов
/ 11 мая 2011

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

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

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

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

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

39 голосов
/ 11 мая 2011

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

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

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

17 голосов
/ 11 мая 2011

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

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

4 голосов
/ 22 ноября 2014

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

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

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

0 голосов
/ 11 мая 2011

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

...