2010-07-15 4 views
12

J'ai une classe nommée WhatClass avec un champ List. J'ai besoin de pouvoir lire seulement ce champ, donc j'ai utilisé une propriété get pour l'exposer à d'autres objets.Comment rendre la méthode Add de List protégée, tout en exposant List avec la propriété get?

public class WhatClass 
{ 
    List<SomeOtherClass> _SomeOtherClassItems; 

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

Cependant, il se trouve que tout objet peut appeler

WhatClass.SomeOtherClassItems.Add(item); 

Comment puis-je empêcher cela?

Répondre

21

Comme d'autres l'ont dit, vous êtes à la recherche de la méthode d'extension .AsReadOnly().

Cependant, vous devez stocker une référence à la collection au lieu de le créer au cours de chaque accès à la propriété:

private readonly List<SomeOtherClass> _items; 

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

    this.Items = _items.AsReadOnly(); 
} 

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

Ceci est d'assurer que x.Items == x.Items est vraie, ce qui pourrait autrement être très inattendu pour les consommateurs de l'API.

ReadOnlyCollection<> communique votre Révéler l'intention d'une collection en lecture seule pour les consommateurs. Les changements à _items seront reflétés dans Items.

+0

Vous voudrez peut-être d'élaborer pour les masses ce qui se passe lorsque vous ajoutez à _items et comment vous traitez avec cette ... –

+2

@ Dave - L'état de documents qui change sera reflétée dans l'emballage. – ChaosPandion

+0

Bryan, merci beaucoup pour cette réponse, même si je n'ai pas besoin d'un mot-clé readonly ici. –

5

Utilisation List<T>.AsReadOnly:

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

Cela renverra un ReadOnlyCollection, qui lancera une exception si un client appelle Ajouter à travers l'interface. De plus, le type ReadOnlyCollection n'expose pas une méthode Add publique.

+5

Ne pas faire une nouvelle instance à chaque fois. – SLaks

+1

@ SLaks: Je vois ce que vous voulez dire, mais c'est une micro-optimisation et je crois que c'est plus facile à lire de cette façon. ReadOnlyCollection est petit et le GC est bon à traiter avec de petits objets de courte durée, et vous êtes tout aussi susceptibles de liquider l'utilisation de la mémoire en ajoutant un champ et un objet ReadOnlyCollection que vous n'avez pas besoin pour chacun de vos classes . – Quartermeister

+2

L'attribution d'objets dans une propriété getter est une mauvaise idée. Les gens supposent généralement que l'accès à un getter de propriété n'est rien de plus qu'une lecture en mémoire, et va donc accéder à la propriété plusieurs fois dans de grandes boucles imbriquées. – SLaks

6

Vous recherchez le ReadOnlyCollection<T> class, qui est un wrapper en lecture seule autour d'un IList<T>.

Depuis le ReadOnlyCollection<T> reflète les changements dans la liste sous-jacente, vous n'avez pas besoin de créer une nouvelle instance à chaque fois.

Par exemple:

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

    List<SomeOtherClass> _SomeOtherClassItems; 

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

Merci pour votre réponse. Vous avez mentionné la classe ReadOnlyCollection , mais je ne l'ai pas incluse dans le code, mais je l'ai compris. Merci une fois de plus. –

Questions connexes