|
|
連載:[完全版]究極のC#プログラミング
Chapter16 LINQとメソッド構文
川俣 晶
2010/03/29 |
|
|
16.15 メソッド構文のlet句
最後にlet句のメソッド構文への書き換えを説明しよう。これもまた、知らないと何をどう書き換えてよいかわからず悩む可能性のある難物である。
前章のサンプルコード、リスト15.27を、全体を示す形でリスト16.14として再掲しよう。
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
let cn = conversion(n)
from m in b select cn + 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: 3
}
}
|
|
リスト16.14 変換メソッドを呼び出すクエリ式(let句使用) |
このサンプルコードは、conversionメソッドの呼び出し回数を最少にするためにlet句を使用している。let句を使用しない場合は9回呼ばれるが、let句を使用すると3回で済む(詳しくは前章「15.21 let句」を参照)。
メソッド構文に書き換える場合も、この効能を維持しなければ意味がない。しかし、let句と1対1で対応するLetメソッドは存在しない。では、どのように書き換えるのだろうか?
実は、let句自体を使わずとも、同じ効能を持つクエリ式を記述できる。次のように、let句の代わりにネストしたクエリ式を使えば、conversionメソッドの呼び出し回数を3にしたままでlet句を除去できる。
var q = from cn in (from n in a select conversion(n))
from m in b select cn + m;
|
|
これと等価なメソッド構文のクエリは容易に記述できる。内側のクエリ式は単純にSelectメソッドに置き換えられる。外側のクエリ式は複数の対象を選択するので、「SelectManyメソッド」を使う。これで次のように記述可能になる。
var q = a.Select((n) => new { n, cn = conversion(n) })
.SelectMany((c)=>b, (d,m)=>d.cn + m);
|
|
ここで注目すべき点は、式がネストする階層である。let句を使わないクエリ式は2つのクエリ式がネストしていた。let句の効能は、このネストを解消し、1つのクエリ式ですべてを記述可能にする点にあった。しかし、メソッド構文では、式のネストがそもそも最初から発生していない。これはクエリ式と違って、Selectメソッドは式の終わりを意味せず、その後に継続が可能であるからだ。つまり、ネストを解消するというlet句の効能はメソッド構文では意味がない。そのため、let句は単純にSelectメソッドに置き換えればよい。
【Exercise】練習問題
次のクエリ式と同等の機能を持つメソッド構文を選べ。
var query = from x in y where x.a select x.b;
|
|
var query = y.Where((x) => x.a);
var query = y.From(x).Where(x.a).Select(x.b);
var query = y.Where((s) => s.a).Select((t) => t.b);
var query = Where((x,y) => x.a).Select((x) => x.b);
var query = From(y).Where((x) => x.a).Select((x) => x.b);
◎解答:「3」(この行をマウスで選択してください)
Insider.NET 記事ランキング
本日
月間