The classic C# error, and two clean fixes.

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