IList<T>
が配列 ( T[]
)の場合、onと同様にArray.ForEachメソッドがあります。カスタムまたは好みの拡張メソッドを作成できます。ForEach
List<T>
IList<T>
IEnumerable<T>
public static void ForEach<T>(this IList<T> list, Action<T> action)
{
foreach (T t in list)
action(t);
}
元のコレクションのオブジェクトが変更されるという事実に注意する必要がありますが、命名はそれを暗示していると思います.
-------------------------------------------------- -------------------------------------------------- --------------------------------
私は電話することを好みます:
people.Where(p => p.Tenure > 5)
.Select(p => p.Nationality)
.ForEach(n => AssignCitizenShip(n);
よりも
foreach (var n in people.Where(p => p.Tenure > 5).Select(p => p.Nationality))
{
AssignCitizenShip(n);
}
もしそうなら、で拡張メソッドを作成できますIEnumerable
。終了呼び出しがクエリForEach
を実行することに注意してください。Linq
必要ない場合は、yield
ステートメントを使用してIEnumerable<T>
backを返すことで延期することもできます。
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
foreach (T t in list)
{
action(t);
yield return t;
}
}
これで副作用の問題は解決しますが、個人的には、ForEach
最終的に呼び出しを実行するという名前のメソッドが好きです。
-------------------------------------------------- -------------------------------------------------- -------------------------------
好みに関する反対意見に対処するために、これよりも優れた Eric Lippert からのリンクを次に示します。彼を引用するには:
「最初の理由は、そうすることは、他のすべてのシーケンス演算子が基づいている関数型プログラミングの原則に違反することです。明らかに、このメソッドへの呼び出しの唯一の目的は、副作用を引き起こすことです。式の目的は、値を計算することです。副作用を引き起こさない. ステートメントの目的は副作用を引き起こすことです. このことの呼び出し場所は式に非常によく似ています. 「ステートメント式」のコンテキストで使用する必要があります。) 副作用にのみ役立つ唯一無二のシーケンス演算子を作成するのは、私には合いません。
2 番目の理由は、そうすることで言語に新たな表現力がまったく追加されないことです。」
エリックは、それが悪いことだと言っているのではありません。デフォルトで構成を含めないという決定の背後にある哲学的な理由にすぎません。Linq
の関数がコンテンツに作用するべきではないと思われる場合は、IEnumerable
実行しないでください。私はそれが何をするかをよく知っているので、個人的には気にしません。コレクションクラスに副作用を引き起こす他のメソッドとして扱います。必要に応じて、関数に入ってデバッグすることもできます。これはそれ自体からの別のものLinq
です。
people.Where(p => p.Tenure > 5)
.Select(p => p.Nationality)
.AsParallel()
.ForAll(n => AssignCitizenShip(n);
私が言うように、これらについて悪いことは何もありません。個人的な好みです。ネストされた s に対して、またはループ内で実行するコードが複数行含まれている場合は、これを使用しません。foreach
foreach
しかし、私が投稿した簡単な例については、気に入っています。すっきりと簡潔に見えます。
編集:パフォーマンス リンクを参照してください: List<T>.ForEach が標準の foreach よりも速いのはなぜですか?