Почему массив реализует 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: коллекция имеет фиксированный размер" и возникла потому, что массив не может динамически увеличить свою емкость. Его емкость определяется при создании объекта массива.