Liste en lecture seule ou liste non modifiable dans .NET 4.0

100

D'après ce que je peux dire, .NET 4.0 manque toujours de listes en lecture seule. Pourquoi le framework manque-t-il toujours de cette fonctionnalité? N'est-ce pas l'une des fonctionnalités les plus courantes pour la conception axée sur le domaine ?

L'un des rares avantages de Java sur C # est celui-ci sous la forme de la méthode Collections.unmodifiablelist (list) , qui semble être attendue depuis longtemps dans IList <T> ou List <T>.

L'utilisation IEnumerable<T>est la solution la plus simple à la question - ToListpeut être utilisée et renvoie une copie.

Chris S
la source
Il semble que la seule vraie façon d'avoir une vraie lecture seule List<T>est d'écrire la vôtre, il n'y a pas de classe intégrée que je connaisse qui prend en charge toutes les fonctionnalités «lecture seule» prêtes List<T>à l'emploi comme les Containsrequêtes LINQ, etc.
jrh

Réponses:

146

Vous recherchez ReadOnlyCollection, qui existe depuis .NET2.

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

ou

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

Cela crée une lecture seule vue , ce qui reflète les modifications apportées à la collection enveloppée.

LukeH
la source
1
Je me sens un peu stupide d'avoir posé cette question maintenant - et je ne suis pas au courant de ReadOnlyCollection
Chris S
54
ne soyez pas - moi non plus, quand je suis allé chercher la même chose et que j'ai trouvé votre question
Roland Tepp
9
C'est une classe extrêmement difficile à trouver. C'est dans l'espace de noms System.Collections.ObjectModel au lieu de System.Collections.Generic où je m'attendrais à le trouver. Je suppose que c'est parce que c'est là qu'il se trouvait avant que l'espace de noms générique n'existe. Pourtant, je m'attendrais à ce que la classe de base reste dans ObjectModel et que la classe générique soit ajoutée à Generic. Je suppose qu'ils avaient leurs raisons, mais je trouve cela ennuyeux.
BlueMonkMN
5
@BlueMonkMN: Veuillez consulter cet article pour découvrir pourquoi il est séparé de l'espace de noms Collections.Generic.
Uchitha
7
Mais ce n'est pas une liste, c'est une collection. Donc, si vous l'utilisez, vous devez modifier tout votre code pour utiliser Collection au lieu de List.
Roman Zabicki
13

Pour ceux qui aiment utiliser les interfaces: .NET 4.5 ajoute l' IReadOnlyListinterface générique qui est implémentée par List<T>exemple par.

Il est similaire à IReadOnlyCollectionet ajoute une Itempropriété d'indexeur.

Martin
la source
11

Si le modèle le plus courant de la liste consiste à parcourir tous les éléments IEnumerable<T>ou IQueryable<T>peut également agir comme une liste en lecture seule.

Ana Betts
la source
4
Si vous exposez votre List en tant que IEnumerable, le consommateur peut simplement la renvoyer vers List et la modifier.
JulianR
4
Bien sûr, mais ce n'est pas censé être une mesure à toute épreuve - vous pourriez aussi probablement lire les champs privés et retrouver la liste originale. Il s'agit plutôt de décrire l'intention que cela reste en lecture seule.
Ana Betts
5
Vous ne modifiez pas la liste d'origine en appelant ToList()non plus, juste une copie
Chris S
Notez que ce IEnumerablen'est pas un ensemble complet de méthodes "en lecture seule", par exemple il ne contient pas de méthodes comme Contains.
jrh
8

Dans la version 2.0, vous pouvez appeler AsReadOnlypour obtenir une version en lecture seule de la liste. Ou enveloppez un existant IListdans un ReadOnlyCollection<T>objet.

Paul Alexander
la source
c'est l'équivalent de Collections.unmodifiablelist (list) I was after
Chris S
J'ai manqué cela dans .NET 4 parce que j'utilisais un IList <T> au lieu d'un vrai List <T>. Assurez-vous de noter qu'AsReadOnly est toujours disponible dans .NET 4 tant que vous avez affaire à une liste <T>.
BlueMonkMN