2010-07-15 6 views
12

Tengo una clase llamada WhatClass que tiene el campo Lista en ella. Necesito poder leer solo este campo, así que utilicé una propiedad get para exponerla a otros objetos.¿Cómo hacer que el método Add de List esté protegido, mientras se expone List con get property?

public class WhatClass 
{ 
    List<SomeOtherClass> _SomeOtherClassItems; 

    public List<SomeOtherClass> SomeOtherClassItems { get { return _SomeOtherClassItems; } } 
} 

Sin embargo resulta que cualquier objeto puede llamar

WhatClass.SomeOtherClassItems.Add(item); 

¿Cómo puedo evitar esto?

Respuesta

21

Como han dicho otros, que busca el método .AsReadOnly() extensión.

Sin embargo, debe almacenar una referencia a la colección en lugar de crearlo durante cada acceso a la propiedad:

private readonly List<SomeOtherClass> _items; 

public WhatClass() 
{ 
    _items = new List<SomeOtherClass>(); 

    this.Items = _items.AsReadOnly(); 
} 

public ReadOnlyCollection<SomeOtherClass> Items { get; private set; } 

Esto es para asegurar que x.Items == x.Items es cierto, que de otro modo podría ser muy inesperado para los consumidores de la API.

Exponer ReadOnlyCollection<> comunica su intención de una colección de solo lectura a los consumidores. Los cambios a _items se reflejarán en Items.

+0

Es posible que desee elaborar para las masas lo que sucede cuando agrega a _artículos y cómo lidia con eso ... –

+2

@Dave - Los documentos indican que los cambios se reflejarán en el contenedor. – ChaosPandion

+0

Bryan, muchas gracias por esta respuesta, aunque no necesito una palabra clave de solo lectura aquí. –

5

Uso List<T>.AsReadOnly:

public ReadOnlyCollection<SomeOtherClass> SomeOtherClassItems 
{ 
    get 
    { 
     return _SomeOtherClassItems.AsReadOnly(); 
    } 
} 

Esto devolverá un ReadOnlyCollection, que será una excepción si un cliente llama Añadir a través de la interfaz. Además, el tipo ReadOnlyCollection no expone un método público de Agregar.

+5

No crea una nueva instancia cada vez. – SLaks

+1

@SLaks: Veo su punto, pero eso es una micro-optimización y creo que es más fácil de leer de esta manera. ReadOnlyCollection es pequeño y el GC es bueno para tratar objetos pequeños de corta vida, y es probable que termine usando más memoria al agregar un campo y un objeto ReadOnlyCollection que no necesita para cada una de sus clases . – Quartermeister

+2

La asignación de objetos en un getter de propiedades es una mala idea. La gente generalmente asume que acceder a un getter de propiedades no es más que una lectura de memoria, y por lo tanto accederá a la propiedad muchas veces en bucles anidados grandes. – SLaks

6

Usted está buscando el ReadOnlyCollection<T> class, que es un envoltorio de sólo lectura en torno a un IList<T>.

Dado que ReadOnlyCollection<T> reflejará los cambios en la lista subyacente, no es necesario crear una nueva instancia cada vez.

Por ejemplo:

public class WhatClass { 
    public WhatClass() { 
     _SomeOtherClassItems = new List<SomeOtherClass>(); 
     SomeOtherClassItems = _SomeOtherClassItems.AsReadOnly(); 
    } 

    List<SomeOtherClass> _SomeOtherClassItems; 

    public ReadOnlyCollection<SomeOtherClass> SomeOtherClassItems { get; private set; } 
} 
+0

Gracias por su respuesta. Usted mencionó la clase ReadOnlyCollection , pero no la incluyó en el código, pero lo he descubierto. Gracias otra vez. –