Ich habe den klassischen Fall, dass versucht wird, ein Element aus einer Sammlung zu entfernen, während es in einer Schleife aufgelistet wird:
List<int> myIntCollection = new List<int>();
myIntCollection.Add(42);
myIntCollection.Add(12);
myIntCollection.Add(96);
myIntCollection.Add(25);
foreach (int i in myIntCollection)
{
if (i == 42)
myIntCollection.Remove(96); // The error is here.
if (i == 25)
myIntCollection.Remove(42); // The error is here.
}
Zu Beginn der Iteration nach einer Änderung wird ein InvalidOperationException
ausgelöst, da Enumeratoren nicht mögen, wenn sich die zugrunde liegende Sammlung ändert.
Ich muss während der Iteration Änderungen an der Sammlung vornehmen. Es gibt viele Muster, die verwendet werden können, um dies zu vermeiden , aber keines von ihnen scheint eine gute Lösung zu haben:
Löschen Sie nicht innerhalb dieser Schleife, sondern führen Sie eine separate „Löschliste“, die Sie nach der Hauptschleife verarbeiten.
Dies ist normalerweise eine gute Lösung, aber in meinem Fall muss das Element sofort als "Warten" verschwunden sein, bis nach der Hauptschleife, um das Element wirklich zu löschen, der Logikfluss meines Codes geändert wird.
Anstatt das Element zu löschen, setzen Sie einfach ein Flag auf das Element und markieren Sie es als inaktiv. Fügen Sie dann die Funktionalität von Muster 1 hinzu, um die Liste zu bereinigen.
Dies würde für alle meine Anforderungen funktionieren, bedeutet jedoch, dass sich bei jedem Zugriff auf ein Element viel Code ändern muss, um das inaktive Flag zu überprüfen. Dies ist viel zu viel Verwaltung für meinen Geschmack.
Integrieren Sie die Ideen von Muster 2 irgendwie in eine Klasse, die von abgeleitet ist
List<T>
. Diese Superliste behandelt das inaktive Flag, das Löschen von Objekten nachträglich und macht auch keine als inaktiv gekennzeichneten Elemente für Aufzählungskonsumenten verfügbar. Grundsätzlich werden nur alle Ideen von Muster 2 (und anschließend von Muster 1) zusammengefasst.Gibt es eine solche Klasse? Hat jemand Code dafür? Oder gibt es einen besseren Weg?
Mir wurde gesagt, dass der Zugriff auf
myIntCollection.ToArray()
anstelle vonmyIntCollection
das Problem löst und es mir ermöglicht, innerhalb der Schleife zu löschen.Dies scheint mir ein schlechtes Designmuster zu sein, oder ist es in Ordnung?
Einzelheiten:
Die Liste wird viele Elemente enthalten und ich werde nur einige davon entfernen.
Innerhalb der Schleife werde ich alle Arten von Prozessen ausführen, hinzufügen, entfernen usw., daher muss die Lösung ziemlich allgemein sein.
Das Element, das ich löschen muss, ist möglicherweise nicht das aktuelle Element in der Schleife. Zum Beispiel kann ich mich auf Punkt 10 einer 30-Punkte-Schleife befinden und muss Punkt 6 oder Punkt 26 entfernen. Aus diesem Grund funktioniert es nicht mehr, rückwärts durch das Array zu gehen. ;Ö(