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

Chapter16 LINQとメソッド構文

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

 本記事は、(株)技術評論社が発行する書籍『[完全版]究極のC#プログラミング ― 新スタイルによる実践的コーディング』から、許可を得て転載しています。
 同書籍は、もともと本フォーラムにて連載していた『C# 2.0入門』、『C# 3.0入門』の記事を整理統合し、加筆、修正されたものです。

手元でまとめて読みたい方は、ぜひ書店などにてお買い求めください。

 【注意】本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。

16.1 予約語のエスケープ

 まず軽いが重要な話題から入っていこう。

 クエリ式によくあるワナとして、クエリ式の予約語と使用するキーワードが衝突するという問題がある。

 たとえば、これといって特にひねったコーディングは行っていない次のリスト16.1を見ていただきたい。移動経路クラスのfromとtoはpublicなフィールドだから、FromとToにすべきだよな、といった感想は出るかもしれないが、それは名前付けルールの問題であって、コンパイルが通らないような問題ではない。

 しかし、このコードはコンパイルできない。

using System;
using System.Linq;

class 移動経路
{
  public string from;
  public string to;
}

class Program
{
  static void Main(string[] args)
  {
    移動経路[] 移動経路データ =
    {
      new 移動経路() { from = "新宿", to = "京王八王子"},
      new 移動経路() { from = "新宿", to = "橋本"},
      new 移動経路() { from = "渋谷", to = "吉祥寺"},
    };

    foreach (var 経路 in
          from n in 移動経路データ where n.from == "新宿" select n)
    {
      Console.WriteLine("{0}→{1}", 経路.from, 経路.to);
    }
  }
}
リスト16.1 コンパイルできないサンプル

……\Program.cs(20,52): エラー CS1525: 'from' は無効です。
……\Program.cs(20,57): エラー CS1031: 型が必要です。
……\Program.cs(20,60): エラー CS0742: クエリ本体の後には select 句または group 句が必要です。
……\Program.cs(20,65): エラー CS1002: ; が必要です。
……\Program.cs(20,73): エラー CS1002: ; が必要です。
……\Program.cs(20,73): エラー CS1525: ')' は無効です。
……\Program.cs(20,74): エラー CS1002: ; が必要です。
リスト16.1で発生するコンパイルエラー

 多数のエラーが出ていてわかりにくいが、要するにwhere句の「n.from == "新宿"」という式で使われたfromは無効だということである。

 なぜ無効かといえば、fromはfrom句で使用されるキーワードだからである。しかし、ここがきわめて悩ましいところなのだが、fromはC#の予約語だから使用できない、というわけではない。クエリ式の外部に記述されたfromはいっさいエラーの対象になっていないのである。

 これは、C#の言語仕様拡張のポリシーによって発生した事態といえる。C#では、言語仕様が拡張され、新しいキーワードが導入されるとき、それを予約語扱いしないようになっている。そして、そのキーワードは新規に追加された構文内でのみ特別な意味を発揮するようになっているのである。クエリ式のキーワードも同じで、それに該当する以下のキーワードはクエリ式内でのみ特別な意味を持つようになっている。

from、join、on、equals、into、let、orderby、ascending、descending、select、group、by

 つまり、fromは、クエリ式以外では普通に記述できて普通に機能する何の変哲もないキーワードであるにもかかわらず、クエリ式では使用することができない。

 このような問題を解決するために、C#はもともと「プリフィックス」(@)という機能を持っている。これは、意味のあるキーワードと重複するキーワードを記述する際、先頭に@記号を付けることで、特別な意味付けを発揮させないものである。

 上記のリスト16.1では、where句のfromの先頭に@を付ければよい。

where n.from == "新宿"
 
where n.@from == "新宿"

 これでコンパイルでき、実行できる。

新宿→京王八王子
新宿→橋本
リスト16.1の修正後の実行結果

 もっとも、このプリフィックス「@」はくせもので、悪用するとパッと見た目に反する動作をさせることもできてしまう。次のリスト16.2は、「@false」という名前の定数にtrueの値を割り当てることで、条件判断の見た目の印象を逆転させた例である。

using System;

class Program
{
  private const bool @false = true;

  private static void warn(bool ageOK)
  {
    // 年齢認証がfalseの場合は「ダメ!」
    Console.WriteLine(ageOK == @false ? "飲酒ダメ!" : "飲酒OK");
  }

  static void Main(string[] args)
  {
    int age = 17;     // 僕17歳
    warn(age >= 20);  // お酒は20歳になってから
    // 出力:飲酒OK
  }
}
リスト16.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 記事ランキング

本日 月間