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

Chapter16 LINQとメソッド構文

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

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;
  1. var query = y.Where((x) => x.a);
  2. var query = y.From(x).Where(x.a).Select(x.b);
  3. var query = y.Where((s) => s.a).Select((t) => t.b);
  4. var query = Where((x,y) => x.a).Select((x) => x.b);
  5. var query = From(y).Where((x) => x.a).Select((x) => x.b);

 ◎解答:「3」(この行をマウスで選択してください)End of Article


 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 記事ランキング

本日 月間