2013-05-24 3 views
6

Я делаю выживание и пытаюсь удалить объект, когда он уходит с экрана. Вот код:Удалите объект, когда в a для каждого цикла

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 

Ошибка я получаю: Необработанное исключение типа «System.InvalidOperationException» произошло в mscorlib.dll Дополнительная информация: Коллекция была изменена; операция перечисления может не выполняться.

Если кто-нибудь может помочь, это будет здорово, спасибо.

+2

Вы Канот изменить коллекцию, как это в то время как цикл через него , по понятным причинам, если вы думаете об этом. Получите ссылку на объект, находясь в цикле, затем удалите aterwards – DavidB

ответ

1

.NET действительно не нравится, когда вы меняете коллекцию, когда находитесь в середине перечисления ее содержимого. Вы можете попытаться выполнить цикл foreach в цикле for, если вы планируете удалять элементы из этой коллекции.

13

Вы не можете удалить объект из коллекции во время перечисления. Вы не можете изменять коллекцию вообще. Это вызовет ошибку (Коллекция была изменена, операция перечисления не может быть выполнена). Но вы можете добавить объекты, которые вы хотите удалить/удалить в другую коллекцию:

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 

Эти методы будут вызывать список, чтобы изменить его вариант (который проверяется при перечислении):

  • Добавить
  • Clear
  • Вставка
  • InsertRange
  • Удалить
  • RemoveRange
  • RemoveAt
  • Обратный
  • [связующий индексатор]
  • Сортировка

Другой вариант заключается в использовании For-Loop и петлю в обратном направлении:

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 

Это будет не поднимайте эту ошибку, но она не так читаема. Вам нужно перейти от list.Count - 1 к 0, потому что вы хотите удалить элементы, которые изменили бы свойство Count и индекс, который был доступен до того, как элемент был удален, теперь вызывает ArgumentOutOfRangeException.

Последнее, но не менее, вы можете использовать List.RemoveAll:

lstEnemy.RemoveAll(Function(enemy) enemy.enemy.Left < 0) 
+1

+1 Отличный ответ –

+0

другой вариант - использовать некоторое время. отличный ответ –

0

Одним из примеров использования Entity Framework (ElementAt (я)):

for (int i = 0; i < db.Itens.Count(); i++) 
{ 
    Item item = db.Itens.ElementAt(i); 
    if (item.Id == 0) // put a condition 
    { 
     db.Itens.Remove(item); 
     i--; 
    } 
} 
Смежные вопросы