2010-03-28 2 views
2

J'ai récemment été mordu par le (bien trop commun à mon avis) gotcha de Concat retourne son résultat, plutôt que d'ajouter à la liste elle-même.IEnumerable <T> .Concat - Un remplacement qui peut fonctionner sans changer la référence?

Par exemple.

List<Control> mylist=new List<Control>; 
//.... after adding Controls into mylist 
MyPanel.Controls.Concat(mylist); //This will not affect MyPanel.Controls at all. 

MyPanel.Controls=MyPanel.Controls.Concat(mylist); //This is what is needed, but the Controls reference can not be reassigned (for good reason) 

Y a-t-il un autre moyen de combiner deux listes qui fonctionneront lorsque la référence de la collection est en lecture seule?

Est-ce la seule façon de le faire avec un foreach?

foreach(var item in mylist){ 
    MyPanel.Controls.Add(item); 
} 

Y a-t-il un meilleur moyen sans foreach?

Répondre

5

De nombreuses collections ont une méthode AddRange, winforms ControlCollection is one of them.

MyPanel.Controls.AddRange(mylist.ToArray()); 

Ceci a l'avantage de dire le conteneur vous ajouterez de nombreux contrôles à la fois, il peut retarder les étapes de mise en page jusqu'à ce qu'il soit terminé d'ajouter tous.

+0

Hmm .. Je regardais les arguments et n'a même pas la fonction 'connecter ToArray' à l'utilisation que ... – Earlz

+2

OTOH WRT à votre question sur « la combinaison de deux listes », Liste .AddRange accepte IEnumerable afin que vous puissiez passez directement une autre liste. –

+0

L'ajout de l'appel ToArray ne fait pas grand-chose, sauf que mylist est énuméré deux fois au lieu d'une fois. –

0

En dehors de la chance que vous préférez capitalisé sur ForEach foreach minuscules:

mylist.ForEach(MyPanel.Controls.Add); 
1

Votre question porte sur IEnumerable, et la réponse à cette question est toujours "Non" - un IEnumerable est un "flux" d'éléments uniquement en avant. Toutefois, si vous pouvez utiliser un type plus spécialisé - ICollection, IList etc. - vous pouvez utiliser les méthodes Add ou AddRange si elles sont disponibles.

1
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items) { 
    foreach(T item in items) collection.Add(item); 
} 

Ensuite, vous avez:

anyGenericCollection.AddRange(someSequence); 

Bien sûr quelques collections (List<T>, ControlCollection etc) déjà ont un AddRange - ce qui rend simplement à la disposition de ceux qui ne le font pas.

+0

Ne serait-il pas préférable d'étendre ICollection, pas IList, afin de couvrir des types comme LinkedList? –

+0

@Ben - très probablement ;-p (fixe) –

Questions connexes