ジョイ・オブ・プログラミング:LINQ(前編)

XMLを扱えるLINQ ―LINQ to XML― の基礎を学ぼう

シグマコンサルティング 菅原 英治
2008/04/18
Page1 Page2 Page3

LINQの2つの記述方法

 ここでは、LINQの記述方法について述べます。LINQには、次の2つの記述方法があります。

 (1)クエリ式を使用する記述方法
 (2)メソッド・ベースの記述方法

 2つのうちどちらかがより良い方法ということはありません。どちらでも同じ結果が得られるため、記述したい方法で記述すればよいのです。ただし、それぞれの特色については理解しておく必要があるでしょう。

クエリ式を使用する記述方法

 では、まずクエリ式を使用する記述方法についてです。こちらは、リスト1〜リスト3で利用してきた「from」「where」「select」などの標準クエリ演算子を利用して記述する方法です。現在のところLINQを記述するというと、こちらの方法を利用するのが一般的かもしれません。それぞれの演算子については、次の記事の表1に詳しく解説があります。そちらをご参照ください。

メソッド・ベースの記述方法

 一方、メソッド・ベースの記述方法は、次のリスト4のような記述方法です。このコードは、リスト3をメソッド・ベースの記述方法で書き直したものです。

// 名前の一覧をstring型の配列として定義する
string[] names =
  new string[] { "桑山又左衛門", "野瀬市之丞", "杉山忠兵衛" };

// 名前の文字数が5文字より多いものを選択する
IEnumerable<string> queriedNames =
  names.Where(name => name.Length > 5);

// 結果を出力する
foreach (string name in queriedNames)
  Console.WriteLine(name);
リスト4 リスト3をメソッド・ベースの記述方法で書き直したもの
ソースのダウンロードはこちらから。

 実行するとリスト3と同様の結果が得られることが分かります。リスト4を見ると、リスト3では「from …… select」と記述していた個所の代わりに、太字で示されたコードが記述されていることが分かるでしょう。これが、メソッド・ベースの記述方法です。

 この例では、names配列が持つWhereメソッドを利用しています。Whereメソッドのパラメータに「name => name.Length > 5」というFunc<string,bool>型のラムダ式を渡しています。Whereメソッドでは、渡されたラムダ式を利用して評価した結果が、IEnumerable<string>型のコレクションとして得られます。

 さて、ラムダ式という言葉が出てきました。ラムダ式自体の詳細な解説はここでは行いませんが、次のリスト5を用いて、今回の例におけるラムダ式の意味を簡単に解説します。

// Whereメソッドで利用するラムダ式を定義する
Func<string, bool> wherePredicate = name => name.Length > 5;

// ラムダ式を利用する
bool b1 = wherePredicate("桑山");
  // 2文字なのでb1の結果はfalse
bool b2 = wherePredicate("桑山又左衛");
  // 5文字なのでb2の結果はfalse
bool b3 = wherePredicate("桑山又左衛門");
  // 6文字なのでb3の結果はtrue

// ラムダ式をWhereメソッドのパラメータに渡す
IEnumerable<string> queriedNames = names.Where(wherePredicate);
リスト5 ラムダ式を利用した例

 リスト5では、まず、Whereメソッドで利用するラムダ式を定義しています。「Func<string, bool>」という記述が見慣れないかもしれません。この記述では、パラメータがstring型で、戻り値がbool型であるデリゲートをwherePredicateという変数名で定義しています。そして、wherePredicateデリゲートに対し、「name => name.Length > 5」という式を代入しています。

 続いて作成したラムダ式のデリゲートを利用する例を示しています。wherePredicateデリゲートが、string型の文字列をパラメータに取り、その文字列の文字数が5文字より多いか、少ないかを判定し、bool型の結果で表していることが分かります。

 最後に、ラムダ式をWhereメソッドのパラメータとして渡し利用しています。Whereメソッドでは、names配列の要素を渡されたラムダ式を利用して評価し、その結果が得られることになります。

LINQの2つの記述方法のまとめ

 LINQの2つの記述方法についての解説は以上です。クエリ式を利用するほか、メソッド・ベースの記述方法があることが理解いただけたでしょう。また、メソッド・ベースの記述方法では、ラムダ式を利用していました。

 最初にも述べましたが、2つの記述方法は、どちらも同じ結果を得ることが可能です。特に射影などを行わず単純に何らかの条件でコレクションの選択を行いたい場合は、メソッド・ベースの記述方法でWhereメソッドを利用する方が簡潔に記述できます。

 本稿のサンプル・アプリケーションでは、メソッド・ベースの記述方法を利用しています。

LINQ to XMLについて

 LINQの基礎の最後として、LINQ to XMLについて簡単に解説します。LINQ to XMLは、サンプル・アプリケーションでは利用していません。しかし、LINQでXMLを利用するという本稿のテーマに合致したものなので紹介します。

LINQ to XMLとは

 LINQ to XMLとは、XMLを操作するためにLINQを利用する技術です。MSDNのLINQ to XML の概要に、「.NET Framework プログラミング言語から XML を操作できるようにする、LINQ に対応したメモリ内 XML プログラミング インターフェイス」とあります。

 例えば、LINQ to XMLを利用することで、XMLファイルを読み込み、読み込んだXML要素の値のうち、ある条件を満たしたものを抽出する、ということが可能です。

LINQ to XMLのクラス

 LINQ to XMLは、具体的には、System.Xml.Linq 名前空間内のクラスにより実現されています。詳しくは次のMSDNサイトをご参照ください。

 これらのクラスのうち、今回はXElementクラスを利用した例を示します。

XMLファイルを読み込み、検索する方法

 それでは、XMLファイルを読み込み、検索する方法を紹介したいと思います。次のリスト6では、サンプル・アプリケーションで利用しているレストラン情報を記録したXMLファイルから、得点が80点以上のレストラン名を出力します(コンソール・アプリケーションでレストラン情報を記録したXMLファイルを利用する場合は、ファイルのパスに注意してください。実行する.exeファイルと同じフォルダ内に存在する必要があります)。

// XMLファイルを読み込み、全Restaurant要素を取得する
IEnumerable<XElement> restaurants =
  XElement.Load("Restaurants.xml").Elements("Restaurant");

// 全Restaurant要素のうち、点数が80点以上のRestaurantを選択する
// (メソッド・ベース記述)
IEnumerable<XElement> selectedRestaurants =
  restaurants.Where(restaurant => (int)restaurant.Element("Point") >= 80);

// 下記のクエリ式でも同じ結果となる
// IEnumerable<XElement> selectedRestaurants =
//  from restaurant in restaurants
//  where (int)restaurant.Element("Point") >= 80
//  select restaurant;

// 結果を出力する
foreach (XElement restaurant in selectedRestaurants)
  Console.WriteLine((string)restaurant.Element("Name"));
リスト6 レストラン情報を記録したXMLファイルから、得点が80点以上のレストラン名を出力するプログラム
ソースのダウンロードはこちらから。Restaurants.xmlのダウンロードはこちらから。

 実行すると次のように、得点が80点以上のレストラン名が出力されることが分かります。

本格中華シグマ飯店
洋食 ビストロ工事
カフェ CafeY
和食 酢十
蕎麦 かわかみヤン
リスト6の実行結果

 リスト6のコードを解説します。はじめに、XMLファイルを読み込み、その結果から全Restaurant要素を取得しています。このとき、XElementクラスの静的メソッドであるLoadメソッドでXMLファイルを読み込んでいます。読み込んだ結果は、XElementクラスのインスタンスであり、そのインスタンスのElementsメソッドを利用することで、IEnumerable<XElement>型のRestaurant要素のコレクションを取得しました。

 続いて、取得したIEnumerable<XElement>型のRestaurant要素のコレクションに対し、LINQを利用し、各Restaurant要素のPoint要素(得点)が、80以上のものを選択しています。この選択した結果もIEnumerable<XElement>型のコレクションになります。

 また、LINQをメソッド・ベース記述で記述していますが、参考までに同じ意味のクエリ式をコメントで記述しています。

 最後に、LINQで選択した結果のIEnumerable<XElement>型のコレクションを、出力しています。ここではRestaurant要素のName要素(名前)を出力しています。

 LINQ to XMLの解説は以上です。簡単にXMLファイルを読み込んで、その内容を検索することが可能であることが理解できたでしょう。XElementクラスの利用方法を新たに習得する必要があるため、サンプル・アプリケーションでは、利用していませんが、とても便利な技術です。

 次回の後編では、いよいよサンプル・アプリケーションのソースについて解説します。End of Article



 INDEX
  ジョイ・オブ・プログラミング:LINQ(前編)
  XMLを扱えるLINQ ―LINQ to XML― の基礎を学ぼう
    1.ジョイ・オブ・プログラミングの伝道師「ロブ」
    2.LINQの基礎
  3.LINQ to XMLについて
 
  ジョイ・オブ・プログラミング:LINQ(後編)
  LINQを活用した簡単XMLデータベース・アプリケーション
    1.サンプル・アプリケーションのソース解説
    2.LINQのWhere条件を動的に変更する方法

 ジョイ・オブ・プログラミング


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

本日 月間