小野 修司

 どっとねっとふぁんのオーナー

 LINQ(Language Integrated Query:統合言語クエリー)は,C# 3.0およびVisual Basic 9.0で追加された,データを抽出するための新しいプログラムの記述方法です。LINQの特徴は,簡単な記述でデータの集合から「必要なデータ」の「必要なメンバー」のみを「必要とする順序」で取り出せるところにあります。

(注意:本記事はVisual Studio 2008のベータ版をベースに執筆しています)

LINQのプログラムを見てみよう

 まずは,簡単なサンプル・プログラムを作成してLINQの動作を確認してみましょう。Visual Studio 2008(以下,VS2008)でコンソールアプリケーションのプロジェクトを新規に作成し,リスト1のようなプログラムを記述してください。プログラムを実行すると,Genderの値として1を持つデータがAgeの値が小さい順に以下のように出力されます。

using System;
using System.Linq;

namespace sample1
{
  class Program
  {
    static void Main(string[] args)
    {
      var People = new[]{
        new { Name="アカイ サモン", Gender=1, Age=37},
        new { Name="アオヤマ ショウ", Gender=1, Age=29},
        new { Name="ヤマブキ サイゾウ", Gender=1, Age=31},
        new { Name="ユウキ ミドリ", Gender=2, Age=28},
        new { Name="クロサキ ユウジ", Gender=1, Age=32}
      };

      var query = from p in People
                  where p.Gender == 1
                  orderby p.Age
                  select new { p.Name, p.Age };

      foreach (var item in query)
      {
        Console.WriteLine("名前={0}, 年齢={1}", item.Name, item.Age);
      }

    }
  }
}
リスト1●LINQを使った最初のサンプル・プログラム。言語はC#を使用

名前=アオヤマ ショウ, 年齢=29
名前=ヤマブキ サイゾウ, 年齢=31
名前=クロサキ ユウジ, 年齢=32
名前=アカイ サモン, 年齢=37

 サンプル・プログラムの中で,fromから始まる文がクエリー式と呼ばれるLINQの部分です。クエリー式はSQL文に似ていて,以下のような形になります。

結果を格納する変数 = from データ変数 in データの集合
                     where 抽出条件
                     orderby 抽出順序のキー項目
                     select 抽出するメンバーで構成される新しいクラス ;

LINQ構文の基礎

 では,クエリー式で使われるLINQのクエリー演算子についてそれぞれ見ていきましょう。

●from句

 from句には,foreachを利用する場合と同じように,個々のデータを格納する変数名とデータの抽出の対象となるデータの集合を「in」でつないで記述します。データの集合はIEnumerableインタフェースを継承したものであればなんでもよいので,サンプル・プログラムで利用しているPeopleのような配列のほかに,リスト(LIST)なども利用できます。また,独自に作成したクラスだけでなく,.NET Frameworkが用意している様々なクラスを利用することもできます。

●where句

 where句には抽出条件を記述します。from句で設定した変数名を利用して条件を記述し,この条件が真(true)となるものが抽出の対象となります。複数の抽出条件を組み合わせたい場合は「&&」を使います。例えば,Genderの値が1で,かつAgeの値が30より大きいデータを取り出したいなら,where句の記述は以下のようになります。

where p.Gender == 1 && p.Age > 30

 SQL文の記述に慣れている人だと抽出条件を組み合わせるのについ「AND」を使ってしまいそうですが,クエリー式ではC#の条件式としてtrueが帰ってくる必要があるため,&&演算子を用いることになります。

●orderby句

 orderby句にはデータの並べ替えを行うメンバー名を記述します。デフォルトでは昇順に並びますので,降順にしたい場合には以下のようにメンバー名の後に「descending」を追加します。

orderby p.Age descending

 複数のメンバーを利用して並べ替えを行いたいケース,例えばAgeの値が同じ人がいた場合にName順にしたい,といった場合にはメンバー名を「,(カンマ)」で区切って続けます。

orderby p.Age, p.Name

●select句

 select句では,必要なメンバーだけを取り出して新しいクラスを作ることができます。サンプル・プログラムではNameとAgeの値だけを持つ匿名クラスを作成していますが,ここで元のデータをそのまま利用することも可能です。

●結果の格納

 クエリー式の結果はselect句で作成されたクラスの集合(IEnumerable)となります。サンプル・プログラムでは匿名クラスの集合となるので,「var」を利用することで特に型を指定せずにデータを取り出せるようにしています。

 クエリー式ではjoin句やgroupby句なども使えるので,もっと複雑なクエリーも記述できますが,基本となるのはサンプル・プログラムで示した形になると思います。ここではプログラム中で繰り返しの構文を用いてデータを抽出したり,結果を利用するのに必要な新たなクラスを用意したりといった定型的なわずらわしい作業はありません。覚えやすい簡単な記述で,データの集合から「必要なデータ」の「必要なメンバー」のみを「必要とする順序」で取り出せるということが実感していただけたのではないでしょうか。

 LINQでは,リスト1のように通常のデータの集合(Object)を扱う「LINQ to Objects」だけでなく,XMLファイルを対象する「LINQ to XML」や,SQL Server上のデータを対象とする「LINQ to SQL」など,同じ記述スタイルでデータの抽出を行うことができます。次にLINQ to XMLについて見てみましょう。

XMLデータが簡単に読み込める LINQ to XML

 LINQ to XMLのサンプル・プログラムは,リスト2のようになります。クエリー式の形式はリスト1のLINQ to Objectsの場合と同じです。違っているのはXMLを読み込んでいるXElementオブジェクトの使い方だけとなります。

using System;
using System.Linq;
using System.Xml.Linq;

namespace sample2
{
  class Program
  {
    static void Main(string[] args)
    {
      XElement People = XElement.Parse(
        @"<People>
        <Person>
          <Name>アカイ サモン</Name>
          <Gender>1</Gender>
          <Age>37</Age>
        </Person>
        <Person>
          <Name>アオヤマ ショウ</Name>
          <Gender>1</Gender>
          <Age>29</Age>
        </Person>
        <Person>
          <Name>ヤマブキ サイゾウ</Name>
          <Gender>1</Gender>
          <Age>31</Age>
        </Person>
        <Person>
          <Name>ユウキ ミドリ</Name>
          <Gender>2</Gender>
          <Age>28</Age>
        </Person>
        <Person>
          <Name>クロサキ ユウジ</Name>
          <Gender>1</Gender>
          <Age>32</Age>
        </Person>
        </People>");

        var query = from p in People.Descendants("Person")
                    where (int)p.Element("Gender") == 1
                    orderby (int)p.Element("Age")
                    select new { Name = (string)p.Element("Name"), Age = (int)p.Element("Age") };

          foreach (var item in query)
          {
            Console.WriteLine("名前={0}, 年齢={1}", item.Name, item.Age);
          } 

      }
  }
}
リスト2●LINQ to XMLのサンプル・プログラム

 XElementオブジェクトは,リスト2のようにXMLの文字列を読み込む以外に,Loadメソッドを利用してXMLファイルを読み込むことができます。このとき,Loadメソッドの引数にURLを渡すと,Webサービスから返されるXMLファイルを直接読み込むことも可能です。

 また,XElement内部の要素を取り出すのにElementメソッドが利用でき,リスト2のように(int)や(string)と記述することで簡単にデータの型を指定することができます。XMLになじみの薄いプログラマでも直感的にXML内のデータを扱うことができるのではないでしょうか。

 現在,様々なWebサービスが提供されるようになっています。そのようなWebサービスを簡単に活用する手段としてLINQ to XMLは便利に手軽に使える技術ということができます。