8

サバイバル ゲームを作成していて、オブジェクトが画面から消えたときにオブジェクトを削除しようとしています。コードは次のとおりです。

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 で発生しました 追加情報: コレクションが変更されました。列挙操作が実行されない場合があります。

誰かがそれを助けることができれば、ありがとう。

4

3 に答える 3

15

列挙中にコレクションからオブジェクトを削除することはできません。コレクションをまったく変更することはできません。これにより、エラーが発生します (コレクションが変更されました。列挙操作が実行されない可能性があります)。ただし、削除/削除するオブジェクトを別のコレクションに追加できます。

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

次のすべてのメソッドにより、リストのバージョンが変更されます (列挙中にチェックされます)。

  • 追加
  • クリア
  • 入れる
  • 挿入範囲
  • 削除する
  • 削除範囲
  • 削除場所
  • 逆行する
  • 【インデクサーセッター】
  • 選別

別のオプションは、 a を使用し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必要があり、アイテムが削除される前に使用可能だったインデックスが.0CountArgumentOutOfRangeException

最後になりましたが、次を使用できます List.RemoveAll

lstEnemy.RemoveAll(Function(enemy) enemy.enemy.Left < 0)
于 2013-05-24T11:50:49.250 に答える
1

.NET は、コレクションの内容を列挙している最中にコレクションを変更することを本当に好みません。このようにコレクションから要素を削除することを計画している場合はforeach、ループをループに変更してみてください。for

于 2013-05-24T11:48:57.593 に答える
0

エンティティ フレームワーク (ElementAt(i)) を使用した 1 つの例:

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--;
    }
}
于 2015-06-26T14:28:33.913 に答える