2010-07-15 4 views
12

Ho una classe denominata WhatClass che contiene il campo Elenco. Devo essere in grado di leggere solo questo campo, quindi ho usato una proprietà get per esporla ad altri oggetti.Come rendere protetto il metodo Add dell'elenco, esponendo Elenco con get property?

public class WhatClass 
{ 
    List<SomeOtherClass> _SomeOtherClassItems; 

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

Tuttavia si scopre che qualsiasi oggetto può chiamare

WhatClass.SomeOtherClassItems.Add(item); 

Come posso evitare questo?

risposta

21

Come altri hanno detto, si sta cercando per il metodo .AsReadOnly() estensione.

Tuttavia, è necessario memorizzare un riferimento alla collezione invece di creare durante ogni accesso alle proprietà:

private readonly List<SomeOtherClass> _items; 

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

    this.Items = _items.AsReadOnly(); 
} 

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

Questo per garantire che x.Items == x.Items vale, che potrebbero essere molto inaspettato per i consumatori API.

Exposing ReadOnlyCollection<> comunica agli utenti l'intenzione di una raccolta di sola lettura. Le modifiche a _items si rifletteranno in Items.

+0

Si potrebbe voler elaborare per le masse cosa succede quando si aggiunge _items e come si gestisce con questo ... –

+2

@Dave - I documenti affermano che le modifiche si rifletteranno nel wrapper. – ChaosPandion

+0

Bryan, grazie mille per questa risposta, anche se non ho bisogno di una parola chiave readonly qui. –

5

Uso List<T>.AsReadOnly:

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

Questo restituirà un ReadOnlyCollection, che sarà un'eccezione se un chiamate Client Add attraverso l'interfaccia. Inoltre, il tipo ReadOnlyCollection non espone un metodo di aggiunta pubblico.

+5

Non creare una nuova istanza ogni volta. – SLaks

+1

@SLaks: vedo il tuo punto, ma questa è una micro-ottimizzazione e credo che sia più facile leggere in questo modo. ReadOnlyCollection è piccolo e GC è bravo a gestire piccoli oggetti di breve durata, ed è altrettanto probabile che si finisca per usare più memoria aggiungendo un campo e un oggetto ReadOnlyCollection che non è necessario per ognuna delle tue classi . – Quartermeister

+2

L'allocazione di oggetti in un getter di proprietà è una cattiva idea. Le persone generalmente presumono che l'accesso a un getter di proprietà non è altro che una lettura di memoria, e quindi accederà alla proprietà molte volte in grandi cicli annidati. – SLaks

6

Stai cercando il ReadOnlyCollection<T> class, che è un involucro di sola lettura attorno a uno IList<T>.

Poiché lo ReadOnlyCollection<T> rifletterà le modifiche nell'elenco sottostante, non è necessario creare una nuova istanza ogni volta.

Ad esempio:

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

    List<SomeOtherClass> _SomeOtherClassItems; 

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

Grazie per la risposta. Hai citato la classe ReadOnlyCollection , ma non l'ho inclusa nel codice, ma l'ho capito. Grazie ancora. –

Problemi correlati