Remove an object when in a for each loop
Solution 1
You cannot delete an object from a collection during enumeration. You cannot modify the collection at all. That will cause an error (Collection was modified; enumeration operation may not execute). But you could add the objects that you want to delete/remove to another collection:
Dim removeEnemies = New List(Of enemy)
For Each enemy As enemy In lstEnemy
' ... '
If enemy.enemy.Left < 0 Then
removeEnemies.Add(enemy.enemy)
End If
Next
For Each enemy In removeEnemies
lstEnemy.Remove(enemy)
Me.Controls.Remove(enemy.enemy)
Next
All of the following methods will cause a list to change its version (which is checked during enumeration):
- Add
- Clear
- Insert
- InsertRange
- Remove
- RemoveRange
- RemoveAt
- Reverse
- [the Indexer setter]
- Sort
Another option is to use a For-Loop
and loop it backwards:
For i As Int32 = lstEnemy.Count - 1 To 0 Step -1
Dim enemy = lstEnemy(i)
' ... '
If enemy.enemy.Left < 0 Then
lstEnemy.Remove(enemy)
Me.Controls.Remove(enemy.enemy)
End If
Next
This will not raise that error but it's not as readable. You need to go from list.Count - 1
To 0
because you want to remove items which would change the Count
property and an index that was available before the item was removed causes now an ArgumentOutOfRangeException
.
Last but not least, you can use List.RemoveAll
:
lstEnemy.RemoveAll(Function(enemy) enemy.enemy.Left < 0)
Solution 2
.NET really doesn't like it when you change a collection when you're in the middle of enumerating its contents. You might try chAnging your foreach
loop to a for
loop if you're planning on removing elements from the collection like this.
Tyler Hilbert
Updated on June 23, 2022Comments
-
Tyler Hilbert almost 2 years
I'm making a survival game and trying to remove an object when it goes off the screen. Here is the code:
Public Sub tmrEnemyMove_Tick(sender As Object, e As EventArgs) Handles tmrEnemyMove.Tick Dim koopaAnimation As Boolean For Each enemy As enemy In lstEnemy enemy.enemy.Left = enemy.enemy.Left - 20 If enemy.enemy.Tag = "koopa" Then enemy.enemy.Image = Image.FromFile(Application.StartupPath + "\Graphics\koopa" + Trim(Str(koopaPosition)) + ".png") If koopaAnimation = False Then If koopaPosition = 0 Then koopaPosition = 1 Else koopaPosition = 0 End If End If koopaAnimation = True End If If picMario.Left < enemy.enemy.Left AndAlso enemy.enemy.Left < picMario.Right Or picMario.Left < enemy.enemy.Right AndAlso enemy.enemy.Right < picMario.Right Then If picMario.Top < enemy.enemy.Top AndAlso enemy.enemy.Top < picMario.Bottom Or picMario.Top < enemy.enemy.Bottom AndAlso enemy.enemy.Bottom < picMario.Bottom Then 'MsgBox("Collision") End If End If If enemy.enemy.Left < 0 Then lstEnemy.Remove(enemy) Me.Controls.Remove(enemy.enemy) End If Next End Sub
The error I get is: An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll Additional information: Collection was modified; enumeration operation may not execute.
If anyone could help that would be great, thanks.
-
Guillermo Varini over 6 yearsother option is to use a while. great answer