2011-01-13 17 views
9

tengo alguna clase con List -property:de sólo lectura lista en C#

class Foo { 
    private List<int> myList; 
} 

Quiero dar acceso a este campo sólo para lectura.

I.e. Quiero una propiedad con acceso a Enumerable, Count, etc. y sin acceso a Borrar, Agregar, Eliminar, etc. ¿Cómo puedo hacerlo?

+0

Voy a ir una cabeza y cambiar el título de esta pregunta solo debe leerse porque solo lectura e inmutabilidad son dos temas muy diferentes, aunque preferiría que no los mezclemos. Si buscas inmutabilidad visita http://stackoverflow.com/a/9009748/58961. –

Respuesta

25

Si desea una vista de solo lectura de una lista, puede usar ReadOnlyCollection<T>.

class Foo { 
    private ReadOnlyCollection<int> myList; 
} 
+3

O, más exactamente, una variable privada 'List ' y una propiedad pública 'ReadOnlyCollection ' con un 'get {}' que devuelve la variable. –

+3

@Victor: eso daría acceso al código de llamada a la lista mutable por un simple molde. Probablemente no es lo que quiere el OP. La propiedad readonly podría 'devolver nueva ReadOnlyCollection (myList);' embargo. –

+8

ReadOnlyCollection no es realmente inmutable, ya que contiene un puntero a la lista original; si agrega algo a su lista, readNnly-instance también puede acceder a este nuevo elemento ... pero, tiene razón, cuando se trata de modificaciones- métodos: ¡faltan! –

0

Si declara una lista de solo lectura en su clase, aún podrá agregarle elementos.

Si no desea agregar o cambiar nada, debe usar ReadOnlyCollection<T> como sugirió Darin.

Si desea agregar, eliminar elementos de la lista pero no desea cambiar el contenido, puede usar un readonly List<T>.

9

Yo iría por

public sealed class Foo 
{ 
    private readonly List<object> _items = new List<object>(); 

    public IEnumerable<object> Items 
    { 
     get 
     { 
      foreach (var item in this._items) 
      { 
       yield return item; 
      } 
     } 
    } 
} 
+4

¿Por qué molestarse con el límite de rendimiento al final? –

+0

También el Foo podría implementar IEnumerable – Turowicz

+0

@Jon Skeet: simplemente copie el pasado ... al principio tuve un '// TODO', pero lo reemplacé con un foreach ... ¡gracias por esa pista! –

8

Puede exponer una List<T> como ReadOnlyCollection<T> utilizando el método AsReadOnly()

class Foo { 

    private List<int> myList; 

    public ReadOnlyCollection<int> ReadOnlyList { 
    get { 
     myList.AsReadOnly(); 
    } 
    } 
} 

Lo bueno es que si se agrega/eliminar cualquier cosa de su lista privada también se refleja en la ReadOnlyCollection devuelta

+0

Agradable y limpio, exactamente lo que quería. – AnthonyVO

5

Ahora hay una biblioteca de colecciones inmutables que hace exactamente eso. Que puedes instalar a través de Nuget.

Las clases de colección inmutables son compatibles a partir de .NET Framework 4.5.

https://msdn.microsoft.com/en-us/library/dn385366%28v=vs.110%29.aspx

El espacio de nombres genéricos System.Collections.Immutable ofrece inmutable tipos de colección que se pueden utilizar para estos escenarios, entre ellos: ImmutableArray <T>, ImmutableDictionary < TKey, TValue >, ImmutableSortedDictionary <T>, ImmutableHashSet <T>, ImmutableList <T>, ImmutableQueue <T>, ImmutableSortedSet <T>, ImmutableStack <T>

Ejemplo de Uso:

class Foo 
{ 
    public ImmutableList<int> myList { get; private set; } 

    public Foo(IEnumerable<int> list) 
    { 
     myList = list.ToImmutableList(); 
    } 
} 
Cuestiones relacionadas