Przede wszystkim: terminologia. Jeśli powiesz „lista śmieci”, ludzie pomyślą, że mówisz o śmieciarzu. Nazwijmy to „martwą listą”.
Jak zapewne odkryłeś, stąd twoje pytanie, nie możesz usuwać przedmiotów z kolekcji podczas iteracji. Jeśli Twoja kolekcja jest List<>
najprostszym sposobem na usunięcie z niej przedmiotów:
for(int i = list.Count-1; i >= 0; --i)
{
if(list[i].IsDead)
list.RemoveAt(i);
}
Pamiętaj, że iterujesz wstecz . Możesz usuwać elementy podczas iteracji do przodu, ale jest to bardziej skomplikowane i wymaga goto
. Nie możesz tego zrobić foreach
.
Możesz wykonać usuwanie oddzielnie od pętli aktualizacji. Lub możesz połączyć go w pętlę aktualizacji. Zawsze wykonuj RemoveAt
na końcu pętli - po tym punkcie w pętli list[i]
nie można jej uznać za poprawną (staje się znów ważna przy następnej iteracji).
Zauważ też, że każdy obiekt ma swoją własną IsDead
flagę (jeśli używasz wzorca usuwania, możesz to zrobić IsDisposed
) - tak naprawdę wcale nie musisz utrzymywać „martwej listy”.
Używanie flagi na każdym elemencie jest lepsze ze względu na wydajność, ponieważ unikasz konieczności przeszukiwania listy w celu usunięcia. Jest również preferowany przy projektowaniu - oznacza to, że każdy obiekt może łatwo sprawdzić, czy jest martwy - więc nie wywołujesz przypadkowo żadnych metod na nim (jeśli obiekty te implementują wzór jednorazowy, mogą ObjectDisposedException
w tym przypadku rzucić ).
Jeśli masz kolekcję inną niż a List<>
, usunięcie martwych elementów z tej kolekcji może nadal wymagać utworzenia martwej listy (ponieważ usunięcie podczas iteracji może być niemożliwe). Moim zdaniem, lepiej jest zaprojektować martwą listę tuż przed jej użyciem, iterując kolekcję w poszukiwaniu IsDead
flag, zamiast starać się zachować listę, gdy obiekty są zabijane.
Gdy skończysz z martwą listą, powinieneś Clear()
ją zachować, a następnie pozostawić w pobliżu, aby użyć jej później.