Lista tylko do odczytu lub lista niemodyfikowalna w .NET 4.0

100

Z tego, co wiem, w .NET 4.0 nadal brakuje list tylko do odczytu. Dlaczego frameworkowi nadal brakuje tej funkcjonalności? Czy nie jest to jedna z najpopularniejszych funkcji w projektowaniu opartym na domenie ?

Jedną z nielicznych zalet Java w porównaniu z C # jest to w postaci metody Collections.unmodifiablelist (list) , która wydaje się być od dawna spóźniona w IList <T> lub List <T>.

Użycie IEnumerable<T>jest najłatwiejszym rozwiązaniem pytania - ToListmożna z niego skorzystać i zwrócić kopię.

Chris S.
źródło
Wydaje się, że jedynym prawdziwym sposobem, aby mieć prawdziwe tylko List<T>do odczytu, jest napisanie własnej, nie ma wbudowanej klasy, o której wiem, która obsługuje wszystkie funkcje „tylko do odczytu”, takie List<T>jak Containszapytania LINQ itp.
jrh

Odpowiedzi:

146

Szukasz tego ReadOnlyCollection, co istnieje od .NET2.

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

lub

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

Tworzy to widok tylko do odczytu , który odzwierciedla zmiany wprowadzone w opakowanej kolekcji.

LukeH
źródło
1
Czuję się trochę głupio, zadając to pytanie teraz - i nie wiem o ReadOnlyCollection
Chris S
54
nie bądź - ja też nie, kiedy poszedłem szukać tego samego i znalazłem Twoje pytanie
Roland Tepp
9
To irytująco trudne do znalezienia zajęcia. Znajduje się w przestrzeni nazw System.Collections.ObjectModel zamiast w System.Collections.Generic, gdzie spodziewałbym się go znaleźć. Przypuszczam, że dzieje się tak, ponieważ to było miejsce, w którym istniała przestrzeń nazw Generic. Nadal oczekiwałbym, że klasa bazowa pozostanie w ObjectModel, a klasa generyczna zostanie dodana do Generic. Przypuszczam, że mieli swoje powody, ale mnie to denerwuje.
BlueMonkMN
5
@BlueMonkMN: Zapoznaj się z tym artykułem, aby dowiedzieć się, dlaczego jest on oddzielny od przestrzeni nazw Collections.Generic.
Uchitha
7
Ale to nie jest lista, to kolekcja. Jeśli więc go używasz, musisz zmodyfikować cały kod, aby używał kolekcji zamiast listy.
Roman Żabicki
13

Dla tych, którzy lubią używać interfejsów: .NET 4.5 dodaje ogólny IReadOnlyListinterfejs, który jest zaimplementowany List<T>np. Przez .

Jest podobny do właściwości indeksatora IReadOnlyCollectioni dodaje ją Item.

Jaskółka oknówka
źródło
11

Jeśli najczęstszym wzorcem listy jest iteracja przez wszystkie elementy, IEnumerable<T>lub IQueryable<T>może również skutecznie działać jako lista tylko do odczytu.

Ana Betts
źródło
4
Jeśli ujawnisz swoją Listę jako IEnumerable, konsument może po prostu przesłać ją z powrotem do List i zmodyfikować.
JulianR
4
Oczywiście, ale nie ma to być środek kuloodporny - prawdopodobnie mógłbyś również przeczytać pola prywatne i odszukać oryginalną listę. To bardziej opisanie zamiaru, że powinno to pozostać tylko do odczytu.
Ana Betts
5
Nie zmieniasz oryginalnej listy, dzwoniąc ToList(), tylko kopię
Chris S,
Zauważ, że IEnumerablenie jest to pełny zestaw metod „tylko do odczytu”, na przykład nie zawiera metod takich jakContains .
jrh
8

W wersji 2.0 możesz zadzwonić, AsReadOnlyaby uzyskać wersję listy tylko do odczytu. Lub owinąć istniejący IListw ReadOnlyCollection<T>obiekcie.

Paul Alexander
źródło
to odpowiednik Collections.unmodifiablelist (lista), po którym byłem
Chris S
Brakowało mi tego w .NET 4, ponieważ używałem IList <T> zamiast prawdziwego List <T>. Pamiętaj, aby zauważyć, że AsReadOnly jest nadal dostępny w .NET 4, o ile masz do czynienia z aa List <T>.
BlueMonkMN