Почему List‹T› реализует IReadOnlyList‹T› в .NET 4.5?

Почему List<T> реализует IReadOnlyList<T> в .NET 4.5?

List<T> не только для чтения...


person James Newton-King    schedule 07.03.2013    source источник


Ответы (7)


Поскольку List<T> реализует все необходимые методы/свойства/и т.д. (а затем некоторые) из IReadOnlyList<T>. Интерфейс — это контракт, в котором говорится: «Я могу делать как минимум эти вещи».

В документации для IReadOnlyList<T> говорится, что он представляет собой набор элементов только для чтения.

Вот так. В этом интерфейсе нет методов-мутаторов. Вот что значит только для чтения, верно? IReadOnlyList<T> используется "типичным" (контрактным) способом, а не как маркер.

person Matt Ball    schedule 07.03.2013
comment
Так? В документации для IReadOnlyList‹T› говорится, что он представляет собой набор элементов только для чтения. List‹T› предназначен не только для чтения, так почему же он реализует интерфейс? msdn.microsoft.com/en-us/library/hh192385.aspx - person James Newton-King; 07.03.2013
comment
Интерфейс не гарантирует невозможность изменения списка. Это просто означает, что вы не можете изменить его через интерфейс. - person Brandon; 07.03.2013
comment
@JamesNewton-King Это все семантика. С точки зрения наследования интерфейсов функциональность только для чтения является подмножеством функциональности для чтения и записи. Так вот. - person Andrew Savinykh; 07.03.2013
comment
Вот интересное чтение об интерфейсах IReadOnly... noreferrer">social.msdn.microsoft.com/Forums/en/netfxbcl/thread/ - person Brandon; 07.03.2013
comment
Хорошо, по этой логике, тогда разве IList‹T› не должен реализовывать IReadOnlyList‹T›? Я думаю, это глупо. - person James Newton-King; 07.03.2013
comment
Должно! Но это невозможно, потому что это было бы серьезным изменением. Прочтите ссылку, которую я дал ранее. - person Brandon; 07.03.2013
comment
@JamesNewton-King уверен, что в идеальном мире, где устаревший код и обратная совместимость не вызывают беспокойства, это имело бы смысл. Но в реальном мире это было бы кардинальным изменением. Вы вы не первый, кто об этом подумал. Хороший дизайн API — это сложно. Идеальный дизайн API невозможен. Сделать это правильно с первого раза еще более невозможно. - person Matt Ball; 07.03.2013
comment
Это интерпретация отношения типа и подтипа полезна для начала объектно-ориентированного программирования. Однако это далеко не так. - person Tormod; 07.03.2013
comment
Вот что значит "только для чтения", верно? -- Ну, нет. Я не юрист, но я вполне уверен, что контракт, который читается как только, сильно отличается от того, что читается как по крайней мере. Термин правильно применяется в свойстве IsReadOnly свойства IList, которое равно false, когда возможны чтение и запись. Интерфейс должен называться примерно так: IIndexable. - person nmclean; 04.02.2014
comment
@JamesNewton-King: для .NET было бы полезно включить IImmutableList<T>, который был бы реализован только неизменяемыми коллекциями [не обязательно коллекциями, поддерживаемыми массивом; возврат из IEnumerable<int>.Range может реализовать IImmutableList<int>, заставив индексатор вычислять по запросу значение n-го элемента. - person supercat; 19.06.2014
comment
@MattBall Да, это имеет смысл, спасибо. Было бы неплохо, если бы это имя работало. Возможно, IReadableList вместо IReadOnly - person imma; 23.09.2015

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

Методы/функции описывают, что вы можете прочитать содержимое списка. Интерфейс должен был быть IReadableList вместо IReadOnlyList.

person Rbrt    schedule 05.09.2014
comment
Определенно что-то, чтобы сказать об этом. - person Mark; 20.11.2014
comment
Я согласен; Настораживает только часть названия. - person hypehuman; 20.06.2015

Реализация интерфейса — это не то же самое, что его «маркировка». List<T> также реализует IEnumerable<T>, но это не означает, что вы ограничены простым его перечислением.

Они добавили интерфейсы только для чтения для создания API, а не для того, чтобы вы могли пометить свои типы только для чтения интерфейсом. Это позволяет мне использовать IReadOnlyCollection<T> для аргументов, когда я просто хочу узнать количество элементов в коллекции, не перечисляя их, или IReadOnlyList<T>, когда мне нужно сослаться на элементы в коллекции по их индексу. Это хорошо для всех — я могу точно указать, что мне нужно от вызывающего объекта, и в то же время разрешить ему использовать любой тип коллекции, который он хочет, при условии, что он соответствует минимальному стандарту, который я установил для типа аргумента.

Поэтому я думаю, что более сложный вопрос заключается в том, почему нельзя вам List<T> реализовать IReadOnlyList<T>?

person David Schwartz    schedule 02.08.2013
comment
Аналогичный вопрос почему бы и нет вы задаете в stackoverflow.com/questions/12622539/. Ответ сводится к тому, что это привело бы к поломке обратной совместимости. Мне от этого грустно. - person Tim Sparkles; 29.08.2019

Тот факт, что он реализует интерфейс, не означает, что он доступен только для чтения. Но поскольку он реализует интерфейс, теперь вы можете передать его методам, которые ожидают IReadOnlyList<T>. Таким образом, способ взглянуть на это заключается в том, что он реализует интерфейс списка только для чтения... вместе с некоторыми методами записи.

person Brandon    schedule 07.03.2013

Интерфейсы IReadOnlyList и IReadOnlyCollection несколько сбивают с толку, потому что они не означают, что коллекция доступна только для чтения, просто поддерживается доступ только для чтения. Из документации MSDN (прокрутите вниз до раздела "Примечания").

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

Лучшее имя было бы IReadable, см. Почему универсальное ICollection не реализует IReadOnlyCollection в .NET 4.5?. Кроме того, это означает, что IList должен наследовать IReadOnlyList, хотя это не связано с обратной совместимостью, см. Почему IList<T> не наследуется от IReadOnlyList<T>? .

person Markus Hartmair    schedule 16.10.2016

IReadOnlyList заменяет концепцию «ссылочной неизменности», которая присутствует в C++, но не в C#. Эквивалент С++:

void func(T const* t) {...}

или точно эквивалентно, как некоторые предпочитают:

void func(const T* t) {...}

В нем говорится, что функция func не изменяет объект (объекты), на которые ссылается ее аргумент t, называемый «референтом» t. Он ничего не говорит о том, изменяет ли референт t какой-либо другой код и даже может ли.

Таким образом, интерфейс C# является заменой конструкции компилятора. Почему в C# нет концепции неизменяемости ссылок — исторический вопрос: я думаю, что это была ошибка, но сейчас уже слишком поздно ее исправлять. Я думаю, что предоставление замены интерфейса — это хорошо. Я годами использую точно такой же интерфейс, как IReadOnlyList‹>, но, к счастью, с другим именем IConstList‹>. Я могу заменить использование IConstList‹> на IReadOnlyList‹>.

person Kafka    schedule 07.03.2015

Разве не правда, что код, выполняющий вызовы IReadOnlyList(Of T) к объекту, который реализует этот интерфейс, обычно выполняет один и тот же поток выполнения. Это предотвращает изменение объекта само по себе, если только он не работает в другом потоке выполнения, но для этой ситуации у нас есть вызовы синхронизации, чтобы решить эту проблему.

person Timmy    schedule 05.06.2016