См. Определение класса System.Array
public abstract class Array : IList, ...
Теоретически я смогу написать это и буду счастлив
int[] list = new int[] {};
IList iList = (IList)list;
Я также должен иметь возможность вызывать любой метод из iList
ilist.Add(1); //exception here
Мой вопрос не в том, почему я получаю исключение, а в том, почему Array реализует IList ?
Ответы:
Поскольку массив обеспечивает быстрый доступ по индексу, и
IList
/IList<T>
- единственные интерфейсы коллекции, которые это поддерживают. Так что, возможно, ваш настоящий вопрос: «Почему нет интерфейса для постоянных коллекций с индексаторами?» И на это у меня нет ответа.Для коллекций также нет интерфейсов только для чтения. И мне их не хватает даже больше, чем постоянный размер с интерфейсом индексаторов.
IMO должно быть еще несколько (общих) интерфейсов коллекции в зависимости от функций коллекции. И названия тоже должны были быть другие,
List
ибо что-то с индексатором действительно тупо ИМО.IEnumerable<T>
ICollection<T>
IList<T>
Я считаю, что нынешние интерфейсы коллекций - плохой дизайн. Но поскольку у них есть свойства, говорящие вам, какие методы допустимы (и это часть контракта этих методов), это не нарушает принцип подстановки.
источник
add
и, следовательно, не может быть заменен чем-то, что работает, когда эта способность требуется.IsFixedSize
иIsReadOnly
свойства, это , безусловно , нарушает Телль, не проси принцип и принцип наименьшего удивления . Зачем реализовывать интерфейс, если вы собираетесь выбросить исключения для 4 из 9 методов?Раздел замечания документации по
IList
словамОчевидно, что массивы относятся к категории фиксированного размера, поэтому по определению интерфейса это имеет смысл.
источник
Array
этогоAdd
метода явно реализован метод, что снижает риск его случайного вызова.IList
которая запрещает как модификацию, так и добавление / удаление. Тогда документация больше не верна. : PПотому что не все
IList
s являются изменяемыми (см.IList.IsFixedSize
ИIList.IsReadOnly
), а массивы определенно ведут себя как списки фиксированного размера.Если ваш вопрос действительно «почему он реализует неуниверсальный интерфейс», то ответ таков: они были до появления дженериков.
источник
IList
сам интерфейс сообщает вам, что он не может быть изменяемым. Если бы это было на самом деле гарантированно изменчивыми и массив сказал вам иначе, то это нарушило бы правило.IList<T>
и не нарушает его в случае не общегоIList
: enterprisecraftsmanship.com/2014/11/22/…Это наследие тех времен, когда было непонятно, как работать с коллекциями только для чтения и доступен ли Array только для чтения. В интерфейсе IList есть флаги IsFixedSize и IsReadOnly. Флаг IsReadOnly означает, что коллекцию вообще нельзя изменить, а IsFixedSize означает, что коллекция разрешает модификацию, но не позволяет добавлять или удалять элементы.
Во времена .Net 4.5 было ясно, что для работы с коллекциями только для чтения требуются некоторые «промежуточные» интерфейсы, поэтому
IReadOnlyCollection<T>
иIReadOnlyList<T>
были введены.Вот отличный пост в блоге, описывающий детали: Коллекции только для чтения в .NET
источник
Определение интерфейса IList: «Представляет неуниверсальную коллекцию объектов, к которой можно получить индивидуальный доступ по индексу». Массив полностью удовлетворяет этому определению, поэтому должен реализовывать интерфейс. Исключение при вызове метода Add () - «System.NotSupportedException: коллекция имела фиксированный размер», возникшая из-за того, что массив не может увеличивать свою емкость динамически. Его емкость определяется при создании объекта массива.
источник
Наличие массива, реализующего IList (и транзитивно ICollection), упростило движок Linq2Objects, поскольку приведение IEnumerable к IList / ICollection также будет работать для массивов.
Например, Count () заканчивает внутренним вызовом Array.Length, поскольку он приведен к ICollection, а реализация массива возвращает Length.
Без этого движок Linq2Objects не имел бы специальной обработки для массивов и не работал бы ужасно, или им пришлось бы удвоить код, добавив особый режим для массивов (как они это делают для IList). Они, должно быть, решили сделать так, чтобы массив реализовал IList.
Это мой взгляд на «Почему».
источник
Также детали реализации LINQ Последние проверки для IList, если он не реализует список, им потребуются либо 2 проверки, замедляющие все последние вызовы, либо Last на массиве, принимающем O (N)
источник