Список лише для читання або список, що не змінюється, у .NET 4.0


100

З того, що я можу сказати, .NET 4.0 все ще не має списків, доступних лише для читання. Чому в рамках все ще не вистачає цієї функціональності? Це не один із найпоширеніших фрагментів функціональності для дизайну, керованого доменом ?

Однією з небагатьох переваг, яку Java має над C #, є це у вигляді методу Collections.unmodifiablelist (list) , який, здається, давно назрів у IList <T> або Список <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
не будь - ні я, коли я пішов шукати те саме і знайшов Ваше запитання
Roland Tepp,

9
Це надокучливо важкий клас знайти. Він знаходиться в просторі імен System.Collections.ObjectModel замість System.Collections.Generic, де я б очікував його знайти. Я гадаю, це тому, що саме там він існував до існування загального простору імен. І все-таки я очікую, що базовий клас залишиться в ObjectModel, а загальний клас буде доданий до Generic. Я гадаю, у них були свої причини, але я вважаю це дратівливим.
BlueMonkMN

5
@BlueMonkMN: Будь ласка, зверніться до цієї статті, щоб дізнатися, чому вона відокремлена від простору імен Collections.Generic.
Учіта

7
Але це не Список, це Збірка. Отже, якщо ви використовуєте його, вам потрібно змінити весь код, щоб використовувати колекцію замість списку.
Роман Забицький

13

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

Це схоже на IReadOnlyCollectionта додає Itemвластивість індексатора.



11

Якщо найпоширеніший зразок списку полягає в перегляді всіх елементів, IEnumerable<T>або він також IQueryable<T>може ефективно діяти як список, доступний лише для читання.


4
Якщо ви виставляєте свій Список як IEnumerable, споживач може просто повернути його до списку та змінити його.
JulianR

4
Звичайно, але це не має бути захисною зброєю - ви також можете, мабуть, прочитати приватні поля та відстежити початковий список. Це більше, як опис наміру, що це має залишатися лише для читання.
Ана Беттс

5
Ви не змінюєте оригінальний список, навіть зателефонувавши ToList(), лише копію
Chris S

Зауважте, що IEnumerableце не повний набір методів "лише для читання", наприклад, він не містить таких методів Contains.
jrh

8

У 2.0 ви можете зателефонувати, AsReadOnlyщоб отримати список, доступний лише для читання. Або загортати наявне IListв ReadOnlyCollection<T>об’єкт.


це еквівалент Collections.unmodifiablelist (список), за яким я пішов
Chris S

Я пропустив це у .NET 4, тому що використовував IList <T> замість справжнього списку <T>. Не забудьте помітити, що AsReadOnly все ще доступний у .NET 4, поки ви маєте справу зі списком aa List <T>.
BlueMonkMN

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.