|
|
連載:[完全版]究極のC#プログラミング
Chapter16 LINQとメソッド構文
川俣 晶
2010/03/29 |
|
|
16.2 メソッド構文のLINQ
さて、ここからが本題である。
実は、C#でLINQを使う方法はクエリ式だけではない。これまで長々とクエリ式の書き方を説明してきたが、それは唯一の方法ではない。それどころか、クエリ式とはLINQの全機能を使うことができない不完全なやり方でしかないのである。
では、C#にはクエリ式とは別に、「完全版 真クエリ式」のような構文があるのだろうか? そうではない。そのような構文はC#には存在しない。
実際に存在するのは、「メソッド形式」あるいは「メソッド構文」と呼ばれるLINQの記述方法である。これは、C#の文法上はなんら特別なものではなく、実体はただのメソッド呼び出しである。
実際にその事例を見てみよう。まず、前章で「リスト15.2 最も基本的なLINQ」として紹介したサンプルコードを再掲しよう(リスト16.3参照)。
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
int[] array = { 1, 2, 3 };
var query = from x in array select x;
foreach (int n in query) Console.WriteLine(n);
// 出力:
// 1
// 2
// 3
}
}
|
|
リスト16.3 最も基本的なLINQ |
このサンプルコードのクエリ式の行は次のようなメソッド構文に書き換えることができる。
var query = array.Select((x) => x);
|
|
この書き換えは、機能的に完全に同等である。念のために強調するが、これは「同等の結果が得られる」という意味ではない。別の方法によって同じ結果を得るのでもないし、まして同じ結果になるような別のプログラムを組んだという意味でもない。
上記の2つのコードは、100%完全にあらゆる意味で同等なのである。それは、生成された実行ファイルの中身を調べれば明確にわかる。.NET Reflectorを使ってC#形式で逆コンパイルすると、まったく同じコードが生成されていることがわかる(リスト16.4、リスト16.5参照)。
private static void Main(string[] args)
{
IEnumerable<int> query
= new int[] { 1, 2, 3 }
.Select<int, int>(delegate (int x) { return x; });
foreach (int n in query)
{
Console.WriteLine(n);
}
}
|
|
リスト16.4 クエリ式を使用したケースの逆コンパイル結果 |
private static void Main(string[] args)
{
IEnumerable<int> query
= new int[] { 1, 2, 3 }
.Select<int, int>(delegate (int x) { return x; });
foreach (int n in query)
{
Console.WriteLine(n);
}
}
|
|
リスト16.5 メソッド構文を使用したケースの逆コンパイル結果 |
もちろん、C#ではなくCILに逆アセンブルしても同じである。コンパイラが生成したIDの値が異なる以外、完全に同等のコードが生成されている。
ではなぜこの2つはここまで完全に同等なのだろうか? その理由は実は簡単である。
クエリ式とは実は単なる糖衣構文(シンタックスシュガー)にすぎないからである。糖衣構文とは、書きやすくするために提供される方便としての構文でしかない。つまり、
from x in array select x;
|
|
というクエリ式は、機械的に次のメソッド呼び出しに置換される。
これにより、この2つのコードは実行結果だけでなく、実行するコードそのものまで完全に同等という一致を見せてくれるのである。
Insider.NET 記事ランキング
本日
月間