|
|
連載:[完全版]究極のC#プログラミング
Chapter15 LINQとクエリ式
川俣 晶
2010/03/17 |
|
|
15.21 let句
クエリ式には、もう1つだけ紹介する価値のある句がある。それが「let句」である。
このlet句は、クエリ式の途中で値を範囲変数に保存する機能を持つのだが、クエリ式を書いてみても効能がわかりにくい。なくてもクエリ式は書けてしまうのである。実は筆者も存在意義がわかっていなかったが、本稿を書くに当たって調べたところ、非常に重要な機能があることがわかった。
以下、let句を使わない例(リスト15.26)と、使った例(次ページリスト15.27)の差を見ていただきたい。注目点は、クエリ式から呼び出している変換メソッドの呼び出し回数である。
using System;
using System.Linq;
class Program
{
private static int count = 0;
private static int conversion(int n)
{
count++;
return n; // 何か有意義な変換を行っていると想定する
}
static void Main(string[] args)
{
int[] a = { 1, 2, 3 };
int[] b = { 4, 5, 6 };
var q = from n in a
from m in b
select conversion(n) + m;
foreach (var n in q)
{
Console.WriteLine(n);
}
// 出力: 5 6 7 6 7 8 7 8 9
Console.WriteLine("conversion called: {0}", count);
// 出力:conversion called: 9
}
}
|
|
リスト15.26 変換メソッドを呼び出すクエリ式 |
let句を使う場合は、次のリスト15.27のようにクエリ式を書き換える。
var q = from n in a
let cn = conversion(n)
from m in b
select cn + m;
|
|
リスト15.27 let句を使ったクエリ式 |
5 6 7 6 7 8 7 8 9 conversion called: 3
|
|
リスト15.27のクエリ式の場合の実行結果 |
さて、見てのとおり変換メソッドが呼び出される回数が9回から3回に激減した。減少量は、扱うデータ量(2番目のfrom句の列挙数)が増えればさらに差が大きくなるだろう。
このような差が出る理由は、次のとおりである。
- リスト15.26の第1のfrom句は3回、第2のfrom句も3回の列挙を持つため、select句は3×3=9回繰り返される
- したがって、リスト15.26ではselect句に書かれたメソッド呼び出しも9回発生する
- リスト15.27の第2のfrom句より手前の世界では、第1のfrom句だけが効力を持つ。この世界では、3回だけ列挙が発生する
- リスト15.27の第2のfrom句より手前に書かれたlet句は3回だけ実行される。つまり、メソッド呼び出しは3回しか発生しない
つまり、まとめると、1つのクエリ式内で、列挙回数が増えるタイミングよりも手前に時間のかかる処理を行うと、それだけ大きな高速化を達成できるわけである。let句は式を計算して範囲変数に代入する効能しか持たないが、それを使えば計算を行うタイミングを前倒しし、このような高速化を達成することができるわけである。
Insider.NET 記事ランキング
本日
月間