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

Chapter15 LINQとクエリ式

川俣 晶
2010/03/17
Page 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

15.11 一部項目のみselectする

 実際にLINQを使用する場合、クエリの対象が単なる整数というケースは少ない。それよりも、さまざまな情報を格納したオブジェクトなどを対象にクエリすることになるだろう。

 そこで問題になるのは、多数の情報を含んだオブジェクトを列挙すると、それが重い処理になる可能性があることである。たとえば、参照型オブジェクトを単に右から左に渡すだけならよいが、値型であったり、ファイルやデータベース内の値を取り出したりするとなると、情報量の増加は即、パフォーマンスの悪化に直結する。

 このような問題に対処するために、select句で匿名型オブジェクトを生成するということが行われる。

 具体的な例を紹介しよう。次のリスト15.10の例では、「名前」、「性別」、「所属」という3つの情報を持つオブジェクト群から、性別が男であるアイテムのみを抽出する。結果を表示する際、「性別」の情報を扱う必要はないので(男だけを選んだのでどれも男であるはず)、クエリ結果は「性別」抜きで「名前」、「所属」だけを受け取りたい。このような意図を記述した例である。

using System;
using System.Linq;

class Program
{
  class Person
  {
    public string 名前;
    public string 性別;
    public string 所属;
  }

  static void Main(string[] args)
  {
    Person[] persons =
    {
      new Person() { 名前="古代進", 性別="男", 所属="柔道部" },
      new Person() { 名前="島大介", 性別="男", 所属="ボート部" },
      new Person() { 名前="森雪",   性別="女", 所属="パソコン部" },
    };

    var query = from x in persons where x.性別 == "男"
                              select new { x.名前, x.所属 };

    foreach (var s in query) {
      Console.WriteLine("{0} {1}", s.名前, s.所属);
    }
    // 出力:
    // 古代進 柔道部
    // 島大介 ボート部
  }
}
リスト15.10 匿名型オブジェクトをselectする

 ここでポイントになるのは、select句に記述された「new { x.名前, x.所属 };」という匿名型オブジェクトの生成部分である。これは、次の省略形表記である。

new { 名前 = x.名前, 所属 = x.所属 };

 フィールドの名前を指定せず、使用した初期値の名前をそのままフィールドの名前に転用する仕様は、それ単体では意味が見い出しにくいかもしれない。しかし、select句でクエリ結果の対象のサブセットを作ると思えば、同じ名前が転用されるのは使いやすい仕様である。つまり、含める項目を減らしたいだけなので、含める項目の名前は同じでよいのである。

 さて、ここではクエリ結果を列挙するために「foreach (var s in query)」と型を明示しない変数宣言を行う「var」を使用しているが、これは必須の措置である。匿名型にはソースコード上で明示的に参照できる型の名前が存在しないため、それを明示できないのである。

 さらにこのケースでは、クエリ式本体をvarで宣言した変数で受けなければならない。たとえば、リスト15.2のクエリ式は、varで宣言した変数ではなく、次のような型を明示した変数で受けてもよい。

IEnumerable<int> query = from x in array select x;

 しかし、このリスト15.10の例では同じやり方では受けられない。selectで返される型が匿名なので、「IEnumerable<……>」という書式に書き込むべき型の名前が存在しないからである(もちろん、内部的には型の名前が自動生成されており、リフレクションを使えば取得できるが)。

 つまり、LINQの存在を前提にすると、匿名型やvarキーワードは必須の機能といえるのである。決して、ちょっと便利だから追加した“なくてもよい”機能ではない。C#は何でも機能を増やす無節操な言語ではない。


 INDEX
  [完全版]究極のC#プログラミング
  Chapter15 LINQとクエリ式
    1.15.1 LINQの面白さ
    2.15.2 LINQとは何か?
    3.15.3 「値の集まり」に対する演算
    4.15.4 なぜLINQなのか?
    5.15.5 最も基本的なLINQ
    6.15.6 LINQの本質は列挙
    7.15.7 LINQを使ううえでの注意点
    8.15.8 クエリ結果を加工する
    9.15.9 複数のソースからクエリする
    10.15.10 条件で絞り込む
  11.15.11 一部項目のみselectする
    12.15.12 シンプルなソート
    13.15.13 クエリの接続
    14.15.14 クエリ結果のグループ化
    15.15.15 複数ソースを関連付けるjoin句
    16.15.16 from句とjoin句のパフォーマンス
    17.15.17 join句のグループ化結合
    18.15.18 join句の左外部結合
    19.15.19 単独で使うDefaultIfEmptyメソッド
    20.15.20 内部列挙を伴うfrom句の二重使用
    21.15.21 let句
    22.15.22 クエリのインスタンス化
    23.15.23 クエリ結果の個数を得る
    24.15.24 Anyメソッドと存在チェック/【C#olumn】クエリ式のデバッグテクニック
    25.15.25 まとめ/【C#olumn】LINQの難しさ/【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 記事ランキング

本日 月間