|
|
連載:[完全版]究極のC#プログラミング
Chapter16 LINQとメソッド構文
川俣 晶
2010/03/29 |
|
|
16.9 メソッド構文の複数のソースからクエリする
クエリ式のfrom句に相当するメソッドは、メソッド構文には存在しない。列挙できるオブジェクトがクエリの起点になるのである。しかし、そうすると次のリスト16.11のようなクエリ式をメソッド構文で記述できなくなる。クエリの起点が2つあるからだ。
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
var query = from x in Enumerable.Range(1, 9)
from y in Enumerable.Range(1, 9)
select x + "×" + y + "=" + (x * y).ToString();
foreach (string s in query) Console.WriteLine(s);
// 出力:
// 1×1=1
// 1×2=2
// 1×3=3
//(中略)
// 9×7=63
// 9×8=72
// 9×9=81
}
}
|
|
リスト16.11 掛け算の九九一覧表示 |
この場合、同等のクエリをメソッド構文で記述するには次のようにする。
var query = Enumerable.Range(1, 9)
.SelectMany(
(x) => Enumerable.Range(1, 9),
(x, y) => x + "×" + y + "=" + (x * y).ToString());
|
|
この場合、2つのfrom句というクエリ式を、select句に対応するSelectメソッドの代わりに「SelectManyメソッド」を用いて実現する。このような回りくどい形を取らなければならない。しかも、この例のSelectManyメソッドの引数には2つのラムダ式を渡しており、直感的に動作がわかりやすいとはいいにくい。
この場合のSelectManyメソッドは図16.1のように機能する。
|
図16.1 SelectManyメソッドの動作 |
|
図16.1を見るとわかるとおり、2つのソースから結果を生成する機能を持っていることはわかると思うが、2つのソースのうち1つは前段階から、もう1つは引数から受け取る形式であり、直感的にはわかりにくい。
ちなみに、この例ではSelectManyメソッドの第1引数のラムダ式の仮引数xは使用されていない。しかし、これを使用することもできる。これを使えば、次のような第2段階の列挙が第1段階で列挙された値によって変わるクエリも記述できる。
var query = Enumerable.Range(1, 3)
.SelectMany(
(x) => Enumerable.Range(1, x),
(x, y) => x + "×" + y + "=" + (x * y).ToString());
// 出力:
// 1×1=1
// 2×1=2
// 2×2=4
// 3×1=3
// 3×2=6
// 3×3=9
|
|
第2段階の列挙が第1段階で列挙された値によって変わるクエリ(リスト16.11からクエリのみ差し替え) |
このように、1×……は1回しか列挙されないが3×……は3回列挙されており、回数が変化していることがわかる。これは、仮引数の値を活用したためである。
Insider.NET 記事ランキング
本日
月間