Lista de solo lectura o lista no modificable en .NET 4.0

100

Por lo que puedo decir, .NET 4.0 todavía carece de listas de solo lectura. ¿Por qué el marco todavía carece de esta funcionalidad? ¿No es esta una de las funciones más comunes para el diseño basado en dominios ?

Una de las pocas ventajas que tiene Java sobre C # es esta en la forma del método Collections.unmodifiablelist (list) , que parece estar muy atrasado en IList <T> o List <T>.

Usar IEnumerable<T>es la solución más fácil a la pregunta: ToListse puede usar y devuelve una copia.

Chris S
fuente
Parece que la única forma real de tener una verdadera lectura de solo List<T>es escribir la suya propia, no hay ninguna clase incorporada que yo sepa que admita todas las funciones de "solo lectura" List<T>de las Containsconsultas LINQ, etc.
jrh

Respuestas:

146

Está buscando ReadOnlyCollection, que existe desde .NET2.

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

o

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

Esto crea una vista de solo lectura , que refleja los cambios realizados en la colección envuelta.

LukeH
fuente
1
Me siento un poco estúpido por haber hecho esta pregunta ahora, y no sé sobre ReadOnlyCollection
Chris S
54
no lo esté, yo tampoco, cuando fui a buscar lo mismo y encontré Su pregunta
Roland Tepp
9
Es una clase muy difícil de encontrar. Está en el espacio de nombres System.Collections.ObjectModel en lugar de System.Collections.Generic donde esperaría encontrarlo. Supongo que es porque ahí es donde estaba antes de que existiera el espacio de nombres genérico. Aún así, esperaría que la clase base permanezca en ObjectModel y que la clase genérica se agregue a Generic. Supongo que tenían sus razones, pero lo encuentro molesto.
BlueMonkMN
5
@BlueMonkMN: consulte este artículo para averiguar por qué está separado del espacio de nombres Collections.Generic.
Uchitha
7
Pero eso no es una Lista, es una Colección. Entonces, si lo usa, debe modificar todo su código para usar Colección en lugar de Lista.
Roman Zabicki
13

Para aquellos a los que les gusta usar interfaces: .NET 4.5 agrega la IReadOnlyListinterfaz genérica que se implementa por List<T>ejemplo.

Es similar IReadOnlyCollectiony agrega una Itempropiedad de indexación.

Martín
fuente
11

Si el patrón más común de la lista es iterar a través de todos los elementos, IEnumerable<T>o también IQueryable<T>puede actuar efectivamente como una lista de solo lectura.

Ana Betts
fuente
4
Si expone su Lista como un IEnumerable, entonces el consumidor podría simplemente devolverla a Lista y modificarla.
JulianR
4
Por supuesto, pero no pretende ser una medida a prueba de balas, probablemente también podría leer los campos privados y rastrear la lista original. Es más como describir la intención de que esto sea de solo lectura.
Ana Betts
5
Tampoco está modificando la lista original llamando ToList(), solo una copia
Chris S
Tenga en cuenta que IEnumerableno es un conjunto completo de métodos de "solo lectura", por ejemplo, no contiene métodos como Contains.
jrh
8

En 2.0, puede llamar AsReadOnlypara obtener una versión de solo lectura de la lista. O envuelva un existente IListen un ReadOnlyCollection<T>objeto.

Paul Alexander
fuente
ese es el equivalente de Collections.unmodifiablelist (lista) que buscaba
Chris S
Me perdí esto en .NET 4 porque estaba usando un IList <T> en lugar de un verdadero List <T>. Asegúrese de notar que AsReadOnly todavía está disponible en .NET 4 siempre que esté tratando con una List <T>.
BlueMonkMN