LINQ

【LINQ】LINQの3つの仕組みを詳しく解説

LINQ

データに対し統一的なアクセス手段を提供してくれるLINQは便利な機能ではあるが、クセの強い特徴がある。
基本的にはそれらを意識しなくても効率的な形で実行されるのだが、場合によってはそれが裏目に出る時もある。
そうならないためにも、簡単にLINQの内部処理を理解することは重要である。

以下にLINQの3つの特徴を説明していく。

式を解析して効率化してくれる

【出力結果】

コード上は、IsEven()のループ(※1)を回してから、IsMultipleOf4のループ(※2)を回している。
しかし、出力を見ると、ループが1回にまとまっていることがわかる。(1回のループで※1と※2が同時に実行されている。)
このようにLINQは式を解析して、最適な形で実行をしてくれる。

ただし、最適化が適用されるのは一つのメソッドチェーンで表せる範囲のみ。
例えば、上記のケースだと

という風に一つのメソッドチェーンで表すことができる。

しかし、以下のようなケースでは、IsEven()のループが2回まわってしまい、非効率な形で実施されてしまう。

【出力結果】

LINQは基本的には最適な形で実行されるが、場合によっては非効率な形式になってしまうこともある。

LINQが扱う式は実体がない

LINQが扱う式は実体をもたない。
コレクションに対し、どういう命令をするかという情報だけを返す。
メモリ上に新しいコレクションを生成するわけではない。

この性質のために、上記では非効率な形で式が実行されてしまっている。
(var evensはあくまで、listに対しIsEven()を実施するという情報のみ。
実際にint mul4などで必要になった時に、式が実行される。)

上のケースでIsEven()のループを先に実施してしまいたい場合は、以下のようにコレクションを実体化すればよい。

【出力結果】

結果が必要になったら計算される(遅延実行)

先述したように、LINQの式は実体を持たず、実際にその値が使用される時にならないと計算は実行されない。
この実際にその値が使用される時というのは、より厳密にいうと「値が必要になってMoveNext()メソッドが実行された時」である。

例えば、以下のコードで考えてみる。

これは、メソッドチェーンによって最適化されるので、以下のようになる。

さらに、LINQの実体はforeach文なので、以下のように書き換えられる。

さらにforeach文はコンパイル後は以下のような文に解析される。(参考)

つまり、上記の※1のMoveNext()が実行される時に、はじめて計算が実行されることになる。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">