3

より良い方法がたくさんあることは知っていますが、既存のコードでそれを見たので、これが悪影響を与える可能性があるかどうか疑問に思っています. 削除直後の切れ目に注意してください。したがって、一般的にイテレータは気にしませんが、予期しない動作 (-> 潜在的な例外) は気にします。

foreach (var item in items)
{
    //do stuff
    if (item.IsSomething)
    {
        items.Remove(item); //is this safe???
        break;
    }
}

また、コンパイラが予期しない方法で何かを最適化する可能性はありますか?

4

4 に答える 4

7

コンパイラは、ブロックでDispose()実行される列挙子に対してへの呼び出しを生成しますfinallyが、それは問題にはなりません。アイテムbreakを削除した直後は、列挙子を使用しなくなったため、問題は発生しません。

ただし、(スタイル上の理由などで)別の方法で実行したい場合は、次のように実行できます。

var item = items.FirstOrDefault(i => i.IsSomething);
if (item != null) {
    items.Remove(item);
}

また、少し短くなっています:)(ここでは、コレクションで参照型またはnull許容型を使用していると想定しています)。

于 2013-02-27T08:46:12.420 に答える
2

コンパイラと、アプリケーションに関連するすべてのものは、SC-DRF (データ競合のないプログラムの順次整合性) を保証するため、作成したプログラムと実行されるプログラム (つまり、同じ以外のもの)。複数のスレッド間で共有されていないと仮定すると、これは完全に安全に記述でき、ループ外でitems呼び出す場合を除いて予期しない動作はありません。Remove

于 2013-02-27T08:45:57.963 に答える
1

foreach 内で反復している間はリストを変更できません。

基になるコレクションは、列挙されている間は変更できません。標準的なアプローチは、削除する項目を 2 番目のリストに保持し、Items が列挙された後で、Items から各項目を削除することです。

于 2013-02-27T08:59:42.167 に答える
-1

次に、これを行うことができます-大きなリストを処理する場合はより効率的です(エンティティフレームワークを想定)

var reducedList = items.where(a=>a.IsSomething).toList();
foreach(var item in reducedList)
{
    reducedList.Remove(item);
}

これにより、foreachループの繰り返しが減少します

于 2013-02-27T08:50:07.193 に答える