連載:[完全版]究極のC#プログラミング

Chapter16 LINQとメソッド構文

川俣 晶
2010/03/29
Page 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

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;

というクエリ式は、機械的に次のメソッド呼び出しに置換される。

array.Select((x) => x);

 これにより、この2つのコードは実行結果だけでなく、実行するコードそのものまで完全に同等という一致を見せてくれるのである。


 INDEX
  [完全版]究極のC#プログラミング
  Chapter16 LINQとメソッド構文
    1.16.1 予約語のエスケープ
  2.16.2 メソッド構文のLINQ
    3.16.3 クエリ式とメソッド構文の違い
    4.16.4 絞り込みと結果の生成
    5.16.5 最初の事例の別解
    6.16.6 メソッド構文でのみ可能なクエリ
    7.16.7 メソッド構文のソート
    8.16.8 orderbyの比較オブジェクト
    9.16.9 メソッド構文の複数のソースからクエリする
    10.16.10 メソッド構文のクエリの接続
    11.16.11 クエリ結果のグループ化
    12.16.12 メソッド構文で複数のソースを関連付ける
    13.16.13 メソッド構文のグループ化結合
    14.16.14 メソッド構文の左外部結合
    15.16.15 メソッド構文のlet句/【Exercise】練習問題
 
インデックス・ページヘ  「[完全版]究極のC#プログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間