Why does removing from a list crash your loop?

The classic C# error, and two clean fixes.

Why does removing from a list crash your loop?

The problem

Collection was modified.

foreach ( var enemy in enemies ){    if ( enemy.Health <= 0 )        enemies.Remove( enemy );}

This throws InvalidOperationException the moment the first enemy is removed.

Why it happens

foreach can't follow a moving list.

foreach walks the list step by step. Change the list mid-walk and it loses its place, so C# stops you.

Item removed
everything shifts
foreach
loses its place
C#
throws instead of guessing

Fix 1

Let the list do it.

// removes every dead enemy in one passenemies.RemoveAll( e => e.Health <= 0 );

RemoveAll takes a condition and removes every match. No loop, no crash.

Fix 2

Loop backwards.

for ( int i = enemies.Count - 1; i >= 0; i-- ){    if ( enemies[i].Health <= 0 )        enemies.RemoveAt( i );}

Removing from the end never shifts the items you haven't checked yet.

The rule

Never change a list inside its own foreach.

By condition
RemoveAll
Need the loop
for, backwards
foreach
read only