2009-07-14 7 views
8

Fondamentalement, je souhaite supprimer un élément d'une liste à l'intérieur de la boucle foreach. Je sais que c'est possible en utilisant une boucle for, mais à d'autres fins, je voudrais savoir si cela est réalisable en utilisant une boucle foreach.Modification de la collection lors de l'utilisation d'une boucle foreach dans C#

En python, nous pouvons y parvenir en procédant comme suit:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9] 

for i in a: 
    print i 

    if i == 1: 
     a.pop(1) 

Cela donne le résultat suivant

>>>1 
3 
4 
5 
6 
7 
8 
9 

Mais lorsque vous faites quelque chose de similaire en C#, je reçois un InvalidOperationException, je me demandais S'il y avait un moyen de contourner cela, sans simplement utiliser une boucle for.

Le code C# que j'utilisé lorsque l'exception a été levée:

static void Main(string[] args) 
    { 
    List<string> MyList = new List<string>(new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9"}); 

    foreach (string Item in MyList) 
    { 
    if (MyList.IndexOf(Item) == 0) 
     { 
     MyList.RemoveAt(1); 
     } 

    Console.WriteLine(Item); 
    } 
    } 

Merci à l'avance

Répondre

25

Vous ne pouvez pas le faire. De la documentation pour IEnumerator<T>:

Un recenseur reste valable tant que la collection reste inchangée. Si des modifications sont apportées à la collection, comme l'ajout, la modification, ou la suppression des éléments , l'énumérateur est irrémédiablement invalidé et son comportement est indéfini.

Alternatives sont:

  • construire une nouvelle liste d'éléments à supprimer, puis de les enlever tous après
  • Utilisez une boucle normale « pour » et assurez-vous que vous faites attention de ne pas aller sur le même élément deux fois ou en manquant. (Vous avez dit que vous ne voulez pas faire cela, mais ce que vous essayez de le faire ne fonctionnera pas.)
  • construire une nouvelle collection ne contenant que les éléments que vous souhaitez conserver

la dernière de ces alternatives est la solution LINQ-like, où vous souhaitez généralement écrire:

var newList = oldList.Where(x => ShouldBeRetained(x)).ToList(); 

(. où est ShouldBeRetained quelle que soit la logique que vous voulez, bien sûr) l'appel à ToList() est nécessaire que si vous voulez réellement dans une liste. Cela conduit à un code plus déclaratif qui est souvent plus facile à lire. Je ne peux pas facilement deviner ce que votre boucle originale est destinée à faire (cela semble assez étrange pour l'instant) alors que si vous pouvez exprimer la logique purement en termes de l'objet, cela peut être beaucoup plus clair.

+0

Je me demandais surtout si j'avais manqué quelque chose quelque part avec l'instance foreach, mais si ce n'est pas réalisable, au moins c'est maintenant confirmé! Merci d'avoir répondu – ThePower

1

Vous ne pouvez définitivement pas modifier une collection en utilisant une boucle foreach.

Vous pouvez utiliser une boucle for et gérer l'index pour vous-même ou faire une copie de la collection et comme vous êtes en boucle l'original, supprimez les éléments de la copie qui égalent l'élément dans l'original. Dans les deux cas, ce n'est pas aussi clair ou pratique :).

6

Si tout ce que vous avez besoin est de supprimer tous les éléments qui satisfont une condition que vous pouvez utiliser la méthode List<T>.RemoveAll:

List<string> MyList = new List<string>(new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9" }); 
MyList.RemoveAll(item => item == "1"); 

Notez que cela modifie la liste initiale.

Questions connexes