Список только для чтения или неизменяемый список в .NET 4.0


100

Насколько я могу судить, в .NET 4.0 по-прежнему отсутствуют списки, доступные только для чтения. Почему во фреймворке до сих пор отсутствует эта функциональность? Разве это не одна из самых распространенных функциональных возможностей предметно-ориентированного дизайна ?

Одним из немногих преимуществ Java перед C # является то , что он представлен в форме метода Collections.unmodifiablelist (list) , который, похоже, давно назрел в IList <T> или List <T>.

Использование IEnumerable<T>- самый простой ToListвариант решения вопроса - можно использовать и вернуть копию.


Похоже, что единственный реальный способ иметь истинный режим только List<T>для чтения - это написать свой собственный, я не знаю встроенного класса, который поддерживает все готовые функции «только для чтения» List<T>, такие как Containsзапросы LINQ и т. Д.
— jrh

Ответы:


146

Вы ищете ReadOnlyCollection, который существует со времен .NET2.

IList<string> foo = ...;
// ...
ReadOnlyCollection<string> bar = new ReadOnlyCollection<string>(foo);

или

List<string> foo = ...;
// ...
ReadOnlyCollection<string> bar = foo.AsReadOnly();

Это создает доступное только для чтения представление , которое отражает изменения, внесенные в обернутую коллекцию.


1
Я чувствую себя немного глупо, задав этот вопрос сейчас - и ничего не знаю о ReadOnlyCollection
— Chris S

54
не будь - я тоже, когда я пошел искать то же самое и нашел Ваш вопрос
— Роланд Тепп

9
Это досадно сложно найти. Он находится в пространстве имен System.Collections.ObjectModel вместо System.Collections.Generic, где я ожидал найти его. Полагаю, это потому, что это было до того, как существовало универсальное пространство имен. Тем не менее, я бы ожидал, что базовый класс останется в ObjectModel, а общий класс будет добавлен в Generic. Я полагаю, у них были свои причины, но меня это раздражает.
— BlueMonkMN

5
@BlueMonkMN: обратитесь к этой статье, чтобы узнать, почему она отделена от пространства имен Collections.Generic.
— Uchitha

7
Но это не список, это коллекция. Поэтому, если вы его используете, вам нужно изменить весь свой код, чтобы использовать Collection вместо List.
— Роман Забицкий

13

Для тех, кто любит использовать интерфейсы: .NET 4.5 добавляет общий IReadOnlyListинтерфейс, который, List<T>например, реализован .

Он похож на свойство индексатора IReadOnlyCollectionи добавляет его Item.



11

Если наиболее распространенным шаблоном списка является перебор всех элементов IEnumerable<T>или он также IQueryable<T>может эффективно действовать как список только для чтения.


4
Если вы предоставляете свой список как IEnumerable, то потребитель может просто вернуть его обратно в список и изменить его.
— JulianR

4
Конечно, но это не должно быть пуленепробиваемой мерой - вы также, вероятно, могли бы прочитать личные поля и отследить исходный список. Это больше похоже на описание намерения, чтобы он оставался доступным только для чтения.
— Ана Беттс,

5
Вы также не изменяете исходный список, звоня ToList(), только копию
— Крис С.

Обратите внимание, что IEnumerableэто не полный набор методов «только для чтения», например, он не содержит таких методов, как Contains.
— jrh

8

В 2.0 вы можете позвонить, AsReadOnlyчтобы получить версию списка только для чтения. Или оберните существующее IListв ReadOnlyCollection<T>объект.


это эквивалент Collections.unmodifiablelist (list), который я искал
— Chris S,

Я пропустил это в .NET 4, потому что я использовал IList <T> вместо истинного List <T>. Обязательно обратите внимание на то, что AsReadOnly по-прежнему доступен в .NET 4, если вы имеете дело с List <T>.
— BlueMonkMN

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.