2

delete ブール値が true に設定されているすべてのコインを削除したいのですが、foreach が繰り返し処理している同じコレクションからは削除できないことがわかっています。だから私はコピー(一時)を作成しましたが、同じ例外をスローし続けます:

コレクションが変更されました。列挙操作が実行されない場合があります。

私は何を間違っていますか?これが私のコードです:

List<Coin> temp = coins;
foreach (Coin c in coins)
{
    if (c.delete)
        temp.Remove(c);
    else
        c.somethingElse();
}
coins = temp;
4

3 に答える 3

1

ここで行う最も簡単なことは、 を呼び出すことcoins.RemoveAll(coin => coin.delete);です。(グーグルList.RemoveAll)。これにより、1 つのステートメントですべての「削除」が削除されたコインのリストが残ります。カウンター、ループ変数、一時コピーなどについて心配する必要はまったくありません。したがって、残りのコインを繰り返し処理して、好きなことを行うことができます。

coins.RemoveAll(coin => coin.delete);
foreach (var coin in coins)
    coin.somethingElse();

リストを 1 回だけ反復処理する高速な実装が必要な場合は、次のものが必要です。Removeループで、またはループでソリューションを使用しないでください。これらは処理が遅いRemoveAtためです。ループで使用すると、パフォーマンスが低下します。以下は、各「良い」コインを の位置まで下に移動してからインクリメントするだけなので、いつでもすべての「良い」コインは の下にあります。最後に、上記のすべてのコインを削除すると、「良い」コインだけが残ります。反復は 1 回だけなので、オプションよりも約 2 倍速く、どのソリューションやループよりもはるかに高速です。indexindexindexindexRemoveAllRemoveRemoveAt

var index = 0;
for (var i = 0; i < coins.Count; ++i)
{
    var coin = coins[i];
    if (!coin.delete)
    {
        coin.somethingElse();
        coins[index++] = coin;
    }
}
coins.RemoveRange(index, coins.Count - index);
于 2013-07-25T00:29:49.323 に答える