2009-07-14 19 views
8

Grundsätzlich möchte ich ein Element aus einer Liste entfernen, während in der Foreach-Schleife. Ich weiß, dass dies bei Verwendung einer for-Schleife möglich ist, aber für andere Zwecke würde ich gerne wissen, ob dies mit einer foreach-Schleife möglich ist.Ändern der Sammlung bei Verwendung einer foreach-Schleife in C#

In Python können wir dies erreichen, indem die folgenden Schritte ausführen:

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

for i in a: 
    print i 

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

Dies ergibt die folgende Ausgabe

>>>1 
3 
4 
5 
6 
7 
8 
9 

Aber wenn etwas ähnliches in C# zu tun, ich eine InvalidOperationException, ich habe mich gefragt, Wenn es eine Möglichkeit gäbe, dies zu umgehen, ohne einfach eine For-Schleife zu verwenden.

Der Code in C#, die ich verwenden, wenn die Ausnahme ausgelöst wurde:

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); 
    } 
    } 

Vielen Dank im Voraus

Antwort

25

Sie dies nicht tun können. Aus der Dokumentation für IEnumerator<T>:

Ein Enumerator bleibt gültig, solange die Sammlung unverändert bleibt. Wenn Änderungen an der Sammlung vorgenommen werden, wie Hinzufügen, Ändern oder Löschen von Elementen, ist der Enumerator unwiderruflich ungültig und seine Verhalten ist undefiniert.

Alternativen sind:

  • eine neue Liste von Elementen aufbauen zu entfernen, entfernen Sie sie dann alle danach
  • Verwenden Sie einen normalen „für“ Schleife und stellen Sie sicher, dass Sie vorsichtig sind über nicht los über das gleiche Element zweimal oder fehlt etwas aus. (Sie haben gesagt, Sie dies nicht tun wollen, aber was Sie versuchen, genau das zu tun wird nicht funktionieren.)
  • eine neue Kollektion bauen nur die Elemente enthält, die Sie

behalten wollen die letzte dieser Alternativen ist die LINQ-ähnliche Lösung, wo Sie in der Regel schreiben würde:

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

(. wo ShouldBeRetained ist, was Logik, die Sie wollen, natürlich) der Aufruf von ToList() ist nur erforderlich, wenn Sie wollen es in einer Liste. Dies führt zu mehr deklarativem Code, der oft leichter zu lesen ist. Ich kann nicht leicht erraten, was deine ursprüngliche Schleife tun soll (es scheint im Moment ziemlich seltsam zu sein), wohingegen wenn du die Logik rein in Bezug auf den Gegenstand ausdrücken kannst, kann es viel klarer sein.

+0

Ich habe mich hauptsächlich gefragt, ob ich etwas irgendwo mit der Foreach-Instanz verpasst habe, aber wenn es nicht erreichbar ist, ist es zumindest bestätigt! Danke für die Antwort – ThePower

1

Sie dürfen eine Sammlung auf keinen Fall ändern, wenn Sie eine foreach-Schleife darauf verwenden.

Sie können eine for-Schleife verwenden und den Index für sich selbst verwalten oder eine Kopie der Sammlung erstellen und beim Schleifen des Originals Elemente aus der Kopie entfernen, die dem Objekt im Original entsprechen.

In beiden Fällen ist es nicht ganz so klar oder bequem :).

6

Wenn alles, was Sie brauchen, ist es, alle Elemente zu entfernen, die eine Bedingung erfüllen könnten Sie die List<T>.RemoveAll Methode verwenden:

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

Beachten Sie, dass dies die erste Liste ändert.

Verwandte Themen