|
|
連載:[完全版]究極のC#プログラミング
Chapter16 LINQとメソッド構文
川俣 晶
2010/03/29 |
|
|
16.10 メソッド構文のクエリの接続
ここでは別の形で、クエリ式とはガラッと雰囲気の変わるメソッド構文を紹介しよう。
前章の「15.13 クエリの接続」では、into句を用いて2つのクエリを接続した例を紹介した(リスト16.12参照)。
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
var query = from n in Enumerable.Range(1, 10)
select n * n into m
where m > 50 select m;
foreach (int n in query) Console.WriteLine(n);
}
}
|
|
リスト16.12 1から10までの整数を2乗した値のうち50を超える数値のみを抽出 |
これは、メソッド構文ではどのように記述すればよいのだろうか?
where句にはWhereメソッド、select句にはSelectメソッドがあったように、into句にはIntoメソッドがあるのだろうか? 結論からいうと、Intoメソッドは存在しない。なぜなら、「列挙できるものはクエリできるもの」という原則からいえば、そもそも、into句がなくてもクエリを記述できるからだ。たとえば、リスト16.12のクエリは、次のように書き直せばinto句抜きで記述できる。
var query = from m in (
from n in Enumerable.Range(1, 10) select n * n)
where m > 50 select m;
|
|
ただし、これは「2つのクエリ式」を含む式となる。into句は、これを「1つのクエリ式」で表現するために使われるものである。
さて、これをメソッド構文に置き換えるとき、式は全体で1つの式となるため、“1つの”、“2つの”という区別は意味がなくなる。つまり、into句の存在意義そのものが消滅してしまう。
そして、「列挙できるものはクエリできるもの」という原則からいえば、Selectの出力は「列挙」であるから、これを入力として直接Whereメソッドの前段階に接続してよい。つまり、上記のクエリは次のようなシンプルな1本の式に書き換えられる。
var query = Enumerable.Range(1, 10)
.Select((n) => n * n)
.Where((m) => m > 50)
.Select((m) => m);
|
|
さらにいえば、実はWhereメソッドの返却値そのものが「列挙」であるため、同じ値を列挙させる効能しか発揮していない最後の「.Select((m) => m)」はなくても結果は変わらない。
つまり、次の記述だけで、同等の結果が得られる。
var query = Enumerable.Range(1, 10)
.Select((n) => n * n)
.Where((m) => m > 50);
|
|
このことは、本章p.300で紹介したメソッド構文の「array.Select((x) => x);」という式でも“Select((x) => x)”はなくても同じであることを示す。
このように、クエリ式とは別の形の最適化、シンプル化を行うことができるのが、メソッド構文の特徴といえる。
Insider.NET 記事ランキング
本日
月間