Mam klasyczny przypadek próby usunięcia elementu z kolekcji podczas wyliczania go w pętli:
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.
}
Na początku iteracji po zmianie jest generowany an InvalidOperationException
, ponieważ moduł wyliczający nie lubi, gdy zmienia się podstawowa kolekcja.
Muszę wprowadzić zmiany w kolekcji podczas iteracji. Istnieje wiele wzorców, których można użyć, aby tego uniknąć , ale żaden z nich nie wydaje się mieć dobrego rozwiązania:
Nie usuwaj wewnątrz tej pętli, zamiast tego zachowaj oddzielną listę usuwania, którą przetwarzasz po głównej pętli.
Zwykle jest to dobre rozwiązanie, ale w moim przypadku potrzebuję, aby element zniknął natychmiast, ponieważ „czekam”, aż po zakończeniu głównej pętli, aby naprawdę usunąć element, zmieni się logika przepływu mojego kodu.
Zamiast usuwać element, po prostu ustaw flagę na elemencie i oznacz go jako nieaktywny. Następnie dodaj funkcjonalność wzorca 1, aby wyczyścić listę.
To będzie pracować dla wszystkich moich potrzeb, ale to oznacza, że wiele z kodem będzie musiał zmienić w celu sprawdzenia nieaktywnej flagę za każdym razem element jest dostęp. Jak na mój gust to zdecydowanie za dużo administracji.
W jakiś sposób włącz idee wzorca 2 do klasy, z której pochodzi
List<T>
. Ta Superlista będzie obsługiwać flagę nieaktywną, usuwanie obiektów po fakcie, a także nie będzie ujawniać elementów oznaczonych jako nieaktywne konsumentom wyliczenia. Zasadniczo po prostu zawiera wszystkie idee wzorca 2 (a następnie wzorca 1).Czy istnieje taka klasa? Czy ktoś ma do tego kod? Czy jest jakiś lepszy sposób?
Powiedziano mi, że dostęp
myIntCollection.ToArray()
zamiastmyIntCollection
rozwiązania rozwiąże problem i pozwoli mi usunąć wewnątrz pętli.Wydaje mi się, że to zły wzorzec projektowy, a może jest w porządku?
Detale:
Lista będzie zawierała wiele pozycji, a usunę tylko część z nich.
Wewnątrz pętli będę wykonywać różnego rodzaju procesy, dodawać, usuwać itp., Więc rozwiązanie musi być dość ogólne.
Element, który muszę usunąć, może nie być bieżącym elementem w pętli. Na przykład, mogę być na pozycji 10 w pętli zawierającej 30 pozycji i muszę usunąć pozycję 6 lub pozycję 26. Przechodzenie wstecz przez tablicę nie będzie już działać z tego powodu. ; o (