12

これが許可されていない理由がわかります。

foreach (Thing t in myCollection) {
   if (shouldDelete(t) {
      myCollection.Delete(t);
   }
}

しかし、これはどうですか?

foreach (Thing t in myCollection.Where(o=>shouldDelete(o)) {
   myCollection.Delete(t);
}

これが失敗する理由がわかりません。「Where()」メソッドは明らかに元のコレクションを返さないため、元のコレクションから何かを削除しようとするときに、元のコレクションを列挙していません。

4

6 に答える 6

26

これが失敗する理由がわかりません。

あなたの質問は「なぜこれが失敗するのですか?」だと思います。(質問で実際に質問するのを忘れていました。)

「Where()」メソッドは明らかに元のコレクションを返していません

正しい。"Where" はIEnumerable<T>、フィルタが適用されたコレクションを表す を返します。

そのため、元のコレクションから何かを削除しようとするときに、元のコレクションを列挙していません。

正しくない。元のコレクションを列挙しています。その上にフィルターを置いて元のコレクションを列挙しています。

「Where」を呼び出すと、フィルターが積極的に評価されず、フィルターが適用された元のコレクションの新しいコピーが生成されます。むしろ、元のコレクションを列挙するオブジェクトを提供しますが、フィルターに一致しないアイテムはスキップします。

お店で「全部見せて」と言うと、全部見せてくれる人が全部見せてくれます。「1 キログラムあたり 1 ドルから 5 ドルのリンゴを見せてください」と言うとき、リンゴだけを扱うまったく新しい店舗を建設しているわけではありません。フィルターをかけただけで、以前とまったく同じもののコレクションを見ています。

于 2012-04-16T13:49:45.583 に答える
13

このコードを使用してみてください

myCollection.RemoveAll(x => x.shouldDelete(x));
于 2012-04-16T13:14:46.727 に答える
9

できるよ:

myCollection.RemoveAll(shouldDelete);
于 2012-04-16T13:14:59.293 に答える
6

2 番目のステートメントは、IEnumerable<>リストに対する操作を返します。これは大丈夫なはずです:

foreach (Thing t in myCollection.Where(o=>shouldDelete(o).ToList()) {
   myCollection.Delete(t);
}
于 2012-04-16T13:14:36.567 に答える
2

これは、foreach ループ内でコレクションを変更してはならないためです。foreach ループ全体が実行される前に、それを削除しようとします。したがって、失敗します。

于 2012-04-16T13:13:18.200 に答える
1

Where 拡張メソッドは、渡された述語に基づいてコレクション値をフィルタリングし、IEnumerable を返します。したがって、反復中にコレクションを変更することはできません。

目的に合わせて RemoveAll() を使用できます。

于 2012-04-16T13:17:41.593 に答える