2009-05-20 8 views
3

Je me demande quelle est la meilleure façon d'utiliser les propriétés lorsque vous traitez des collections. Par exemple, j'ai une classe Foo et je veux avoir une liste de cette classe stockée. Lequel des éléments suivants devraient être utilisés:Utilisation correcte des propriétés lors de la gestion d'une collection

private List<Foo> myList; 
private List<Foo> myOtherList = new List<Foo>(); 

maintenant la propriété:

public List<Foo> ListOfFoo 
    { 
    get 
    { 
     return myList; 
    } 
    set 
    { 
     myList= new List<Foo>(value); 
    } 
    } 

Ou devrait l'ensemble être juste à la valeur?

public List<Foo> ListOfFoo 
    { 
    get 
    { 
     return myList; 
    } 
    set 
    { 
     myList= value; 
    } 
    } 
+0

Quelle est la raison pour laquelle la collection devrait être réglable de l'extérieur? – peterchen

+0

Cette propriété se passe sur un contrôle personnalisé qui permettra de glisser-déposer la fonctionnalité pour uniquement les objets Foo dans la liste. Je prévois d'interroger la base de données pour obtenir la liste des objets. Chaque contrôle peut avoir la même liste ou des listes différentes. – Billy

Répondre

2

Choisissez

private List<Foo> myOtherList = new List<Foo>(); 

becuse l'autre déclare juste une référence (qui est définie sur null), l'échantillon ci-dessus déclare une référence à une liste, crée une liste et assignes cette nouvelle liste à la référence.

Choisissez

public List<Foo> ListOfFoo 
    { 
    get { return myList; } 
    set { myList= new List<Foo>(value); } 
    } 

Lorsque vous voulez myList de NE PAS refelect des changements qui se produisent à la liste après il est affecté à myList par exemple

List<string> myFirstList = new List<string>(); 
myFirstList.Add("Hello"); 
myFirstList.Add("World"); 

List<string> mySecondList = new List<string>(myFirstList); 
// mySecondList now contains Hello & world 

myFirstList.Add("Boyo"); 
// myFrist List now contains Hello, world & Boyo 
// mySecondList still contains Hello & world 

Choisissez

public List<Foo> ListOfFoo 
    { 
    get { return myList; } 
    set { myList= value; } 
    } 

Lorsque vous voulez que les deux références au point sur le même objet par exemple

List<string> myFirstList = new List<string>(); 
myFirstList.Add("Hello"); 
myFirstList.Add("World"); 

List<string> mySecondList = myFirstList; 
// mySecondList now contains Hello & world 

myFirstList.Add("Boyo"); 
// myFrist List now contains Hello, world & Boyo 
// mySecondList "also" contains Hello, world & Boyo 

Le « aussi » ci-dessus est entre guillemets, parce qu'en fait, il n'y a qu'une seule liste, et mon premier et mon deuxième point à la même liste.

0

Cela dépend. Lorsque le premier style est utilisé, vous créez une copie de la liste, ce qui est généralement inutile. La convention .Net est pour le setter d'assigner la référence à la propriété. C'est pourquoi je pencherais vers la deuxième option. Toutefois, si vous souhaitez que l'opération de copie ait lieu, la première option correspond à ce que vous recherchez.

2

En général, vous ne souhaitez pas utiliser les propriétés d'un type riche comme List<T> (normalement on utiliserait Collection<T>), et généralement les propriétés d'un type de collection sont en lecture seule - la collection elle-même peut être modifié avec des méthodes telles que Clear, Add etc., ce qui est normalement suffisant.

Par exemple:

class Foo 
{ 
    Collection<Bar> _bars = new Collection<Bar>(); 

    public Collection<Bar> Bars { get { return _bars; } } 
} 

Cela laisse également d'ouvrir pour valider les modifications à la collection en mettant en place un descendant de Collection<T> et en remplaçant les InsertItem, SetItem méthodes etc..

+1

Bien que dans le cas général, vous ne voulez pas utiliser la liste , il est parfaitement acceptable de le faire. Par exemple, si vous avez un objet de données interne. –

+0

TAI - 1, encore j'utiliser la plus petite possible l'interface à l'extérieur (par exemple IList <>) – peterchen

+0

Peterchen - Collection a une plus large, plus facile à utiliser l'interface de IList et Collection peut prendre la mise en œuvre IList envelopper comme le constructeur. À mon humble avis, il n'y a aucune excuse pour utiliser IList sur Collection . –

0

Généralement, exposer seulement une interface (ICollection, IList ou similaire), et en faire lecture seule:

private IList<Foo> m_list = new List<Foo>(); 
public IList<Foo> List {get { return m_list; } } 

Avantage: Vous pouvez modifier la mise en œuvre, par exemple passer d'une liste à une liste observable. Vous devrez peut-être créer le membre m_list du type concret plutôt que l'interface, par ex. utiliser une fonctionnalité supplémentaire.

Avec une liste externe paramétrable, vous rencontrez quelques problèmes. Cependant, il y a des cas où cela est nécessaire:

  • les données peuvent être créées à l'extérieur, et est potentiellement importante, et change fréquemment (par exemple, des dizaines de milliers d'articles)
  • doit être partagé la liste externe entre différentes instances
0

Pourquoi ne pas utiliser l'interface IEnumerator sur la classe et si vous devez utiliser un setter, utilisez une certaine méthode.

De cette façon, vous masquez également l'implémentation de la liste.

class FooBar : IEnumerator 
{ 
    private Collection<Foo> col; 

    public IEnumarator GetEnumerator() 
    { 
    return col.GetEnumerator(); 
    } 

    public void SetList(Collection col) 
    { 
    this.col= col; // you can also make this more general and convert the parameter so it fits your listimpl. 
    } 
} 

class Clazz 
{ 
    private void WhatEver(){ 
    FooBar foobar = new FooBar(); 
    ... 
    foreach(Foo f in foobar) 
    {...} 
    } 
} 
Questions connexes