夢の競演みたび
夢の競演みたび(アンコール)
の続き。
まずは・・・
全力でごめんなさい!!<(_ _;)>
LINQは遅延実行ってのを、知識として取り込んであったはずなのにすっかり忘れていて、前回おもっくそ間違ったことを書いてしまいました。
すでに何名もの方に突っ込みを食らっていますが、
Where()もループぶん回すので
は間違いで、Where()ではループは回さず、foreachで列挙するときにWhere()で指定した条件でコレクションから値がぶっこ抜かれます。
おわびに、ToList()付けたときと付けなかった時の動作を試してみたので、その結果を紹介します。
まず、ToList()無しの場合。
var typedNyans = nyans.Where(x => {
Console.WriteLine(x.Name);
return x.Type != "ほげ";
});
foreach (var nyan in typedNyans)
{
Console.WriteLine("{0}は{1}", nyan.Name, nyan.Type);
}
foreachでの列挙時に条件が評価されていることが見て取れます。
んでもって、次はToList()でWhere()の結果を確定させた場合。
var typedNyans = nyans.Where(x => {
Console.WriteLine(x.Name);
return x.Type != "ほげ";
}).ToList();
foreach (var nyan in typedNyans)
{
Console.WriteLine("{0}は{1}", nyan.Name, nyan.Type);
}
まず、ToList()で一回ループが回ってListが作られ、その後foreachの列挙が行われることが見て取れます。
なお、ToList()、もしくはToArray()を使うかどうかは、渋木さんがコメントでまとめてくださっていますので、以下に転記しておきます。
Where() が内部で独自にループを回すことはないです。
内部的には yield return で実装されているはずなので、Where() によって返された IEnumerable を foreach などで列挙する時、はじめてループは回ります。(遅延実行)
ただし、Where() が返した IEnumerable を foreach などで列挙すると、毎回 Where() の条件式が評価されるので、それが無駄になる場合はあり得ます。
>ToList()は遅延評価を防ぐために静的な情報にするのが目的では?
その方向が妥当です。
ただし、フィルタして作成したコレクションに項目を追加する予定がないなら、ToArray() でもいいと思います。
てか、「追加する予定がない」「追加してほしくない」ことを強調したい時、僕は ToArray() を使います。
みなさん、どうもありがとうございました。勉強になりました。