Schreibgeschützte Liste oder nicht änderbare Liste in .NET 4.0

100

Soweit ich weiß, fehlen in .NET 4.0 immer noch schreibgeschützte Listen. Warum fehlt dem Framework diese Funktionalität noch? Ist dies nicht eine der häufigsten Funktionen für domänengesteuertes Design ?

Einer der wenigen Vorteile, die Java gegenüber C # hat, ist die Methode Collections.unmodifiablelist (list) , die in IList <T> oder List <T> längst überfällig zu sein scheint.

Die Verwendung IEnumerable<T>ist die einfachste Lösung für die Frage - ToListkann verwendet werden und gibt eine Kopie zurück.

Chris S.
quelle
Scheint , wie die einzige wirkliche Möglichkeit , nur eine echte Lese zu haben List<T>ist Ihre eigene zu schreiben, gibt es keine in der Klasse gebaut wird , dass ich an diesen Stützen wissen alle „nur lesen“ verfügt der List<T>aus dem Kasten heraus wie Contains, LINQ - Abfragen etc.
jrh

Antworten:

146

Sie suchen ReadOnlyCollection, was es seit .NET2 gibt.

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

oder

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

Dies schafft eine schreibgeschützte Ansicht , die die eingewickelt Sammlung Änderungen widerspiegelt.

LukeH
quelle
1
Ich fühle mich ein bisschen dumm, diese Frage jetzt gestellt zu haben - und nicht über ReadOnlyCollection bekannt
Chris S
54
nicht sein - ich auch nicht, als ich nach dem gleichen Ding suchte und Ihre Frage fand
Roland Tepp
9
Das ist eine ärgerlich schwer zu findende Klasse. Es befindet sich im System.Collections.ObjectModel-Namespace anstelle von System.Collections.Generic, wo ich es erwarten würde. Ich nehme an, das liegt daran, dass es dort war, bevor der generische Namespace existierte. Trotzdem würde ich erwarten, dass die Basisklasse in ObjectModel bleibt und die generische Klasse zu Generic hinzugefügt wird. Ich nehme an, sie hatten ihre Gründe, aber ich finde es ärgerlich.
BlueMonkMN
5
@BlueMonkMN: In diesem Artikel erfahren Sie, warum er vom Namespace Collections.Generic getrennt ist.
Uchitha
7
Aber das ist keine Liste, es ist eine Sammlung. Wenn Sie es verwenden, müssen Sie Ihren gesamten Code ändern, um Collection anstelle von List zu verwenden.
Roman Zabicki
13

Für diejenigen, die Schnittstellen verwenden möchten: .NET 4.5 fügt die generische IReadOnlyListSchnittstelle hinzu, die beispielsweise von implementiert wird List<T>.

Es ähnelt IReadOnlyCollectioneiner ItemIndexer-Eigenschaft und fügt diese hinzu .

Martin
quelle
11

Wenn das häufigste Muster der Liste darin besteht, alle Elemente zu durchlaufen, IEnumerable<T>oder IQueryable<T>wenn sie effektiv auch als schreibgeschützte Liste fungieren können.

Ana Betts
quelle
4
Wenn Sie Ihre Liste als IEnumerable verfügbar machen, kann der Verbraucher sie einfach in List zurücksetzen und ändern.
JulianR
4
Natürlich, aber es ist nicht als kugelsichere Maßnahme gedacht - Sie könnten wahrscheinlich auch die privaten Felder lesen und die ursprüngliche Liste aufspüren. Es ist eher so, als würde man die Absicht beschreiben, dass dies schreibgeschützt bleiben soll.
Ana Betts
5
Sie ändern die ursprüngliche Liste auch nicht, indem Sie anrufen ToList(), sondern nur eine Kopie
Chris S
Beachten Sie, dass dies IEnumerablekein vollständiger Satz von "schreibgeschützten" Methoden ist, zum Beispiel keine Methoden wie Contains.
jrh
8

In 2.0 können Sie anrufen AsReadOnly, um eine schreibgeschützte Version der Liste zu erhalten. Oder wickeln Sie ein vorhandenes IListin ein ReadOnlyCollection<T>Objekt.

Paul Alexander
quelle
Das ist das Äquivalent zu Collections.unmodifiablelist (Liste), nach der ich
Chris S
Ich habe dies in .NET 4 verpasst, weil ich eine IList <T> anstelle einer echten List <T> verwendet habe. Stellen Sie sicher, dass AsReadOnly in .NET 4 noch verfügbar ist, solange Sie mit einer Liste <T> arbeiten.
BlueMonkMN