はじめに
前回は,ラムダ式についてをご説明しました。 今回は,いよいよC#3.0の新機能として有名なLINQについてをご説明したいと思います。
LINQ(Language Integrated Query)
C#3.0
var q =
from x in this.Collection
where x.Age < 20
orderby x.Name
select new { Code = x.Code, Name = x.Name };
C#2.0
List<Item> q = new List<Item>();
foreach (Member x in this.Collection) {
if (x.Age < 20) {
Item item = new Item();
item.Code = x.Code;
item.Name = x.Name;
q.Add(item);
}
}
q.Sort(delegate(Item a, Item b) {
return string.Compare(a.Name, b.Name); });
上記はthis.Collectionというコレクションのデータから,qという新しいコレクションを以下の規則に準じて生成しています。
- 未成年(Ageプロパティの値が20未満)のアイテムのみ
- 名前順に並べ替え
- Code,Nameプロパティだけをメンバとしたオブジェクトに格納
C#2.0のコードでは,完全に行うべき手続きに対するプログラミングが必要であることに対して,C#3.0のコードではLINQを使うことで,1つのクエリー式を記述しているだけにすぎません。
また,Code,Nameプロパティだけのオブジェクトを作成するための記述は,匿名型によって簡単に実現できていますが,C#2.0では,以前ご説明した通り,別途Itemクラスを用意する必要があります。
どちらのサンプルコードも,以下のコードによって正しく格納できていることを確認できます。
foreach(var item in q) {
Console.WriteLine(item.Code.ToString() + ":" item.Name);
}
LINQとは
LINQとは,言語統合型クエリ(Language Integrated Query)を略した名前です。 その名の示す通り,冒頭のC#3.0のサンプルコードを見ると,クエリー式がコードとして記述できています。
LINQでできること
LINQでは,クエリー式によるコーディングが可能であるため,DBMS(Database Management System)に関するテクノロジーだと誤解している方もいるようですが,これは大きな間違いです。冒頭のサンプルコードのように,コレクションオブジェクトに対しても使うことができます。
- LINQ to Objects
- LINQ to XML
- LINQ to DataSets
- LINQ to SQL
- LINQ to Entities
上記を見ると,我々がプログラミングをする上で,LINQはフロントエンドとしての役割を持っており,バックエンドとしては,オブジェクト・XML・DBMSなどのさまざまなデータソースに対応できることがわかると思います。
なお,冒頭のサンプルコードはLINQ to Objectsになります。
LINQ to Objects
恐らくLINQ to Objectsは,皆さんがLINQに触れるきっかけとなる最も身近なものになるでしょう。
LINQ to Objectsは,IEnumerable,IEnumerable<T>インターフェイスを継承したオブジェクトにクエリー式を適用できます。 ですから,foreachを使ってオブジェクトに対して反復処理をさせる場面では,LINQの利用を検討してみてください。
例えば,次のコードはDataGridViewの左上のセルをカレントセルにするためのコードです。
var q =
from DataGridViewColumn column in grid.Columns
where column.Visible
orderby column.DisplayIndex
select p.Index;
if (q == null) return;
var columnLeftIndex = q.First();
grid.CurrentCell = grid[columnLeftIndex, 0];
grid.Columnsオブジェクトは,DataGridViewColumnCollection型なので,IEnumerable型を継承しています。
IEnumerable<T>のようにコレクションに格納されるデータ型が明確に指定されていないため,各要素の型が推論できません。 このため,from DataGridViewColumn column in grid.Columnsのようにcolumnオブジェクトの型を直前に明記しています。
LINQ to XML
XMLのXElementに対してクエリー式を適用できます。
LINQ to XMLを実行するためには,以下のようにSystem.Xml.Linq名前空間をusingする必要があります。
以下のコードは,“http://blog.example.com/rss”という架空のURLから取得したXML形式のRSSフィードデータを元に,タイトルの一覧を取得するためのサンプルです。
var d = XDocument.Load("http://blog.example.com/rss");
var q =
from x in d.Root.Element("channel").Elements("item")
select x.Element("title").Value;
LINQ to DataSets
ADO.NETのDataSetに対してクエリー式を適用できます。
以下のコードは,MyDataSetのMyDataTableに格納されたデータから,未成年者の名前を取得するためのサンプルコードです。
using(var ds = new MyDataSet()) {
using(var ad = new MyDataTableAdapter()) {
ad.Fill(ds.MyDataTable);
}
var q =
from x in ds.MyDataTable
where x.Age < 20
select x.Name;
}
LINQ to SQL
SQLサーバー上のデータベースに対してクエリー式を適用できます。
以下のコードは,ConnectionStringに指定された接続文字列に基づいてDataContextオブジェクトを作成したものから,未成年者の名前を取得するためのサンプルコードです。 MyDataContextクラスはLINQ to SQLクラスデザイナによって簡単に作成できるようになっています。
using (var db = new MyDataContext(ConnectionString)){
var q =
from x in db.MyDataTable
where x.Age < 20
select x.Name;
}
LINQ to Entities
ADO.NET Entity Frameworkから提供される概念エンティティ(例えば,複数のテーブルを1つのエンティティとするなど)に対してクエリー式を適用できます。
以下のコードは,contextオブジェクトのMyDataTableエンティティから,未成年者の名前を取得するためのサンプルコードです。
var q =
from x in context.MyDataTable
where x.Age < 20
select x.Name;
}
クエリー式の正体
クエリー式の正体は,シンタックスシュガーです。 従って,クエリー式を使わずに記述することもできます。
以下の2つのコードを見比べてみてください。
var q =
from x in this.Collection
where x.Age < 20
orderby x.Name
select new { Code = x.Code, Name = x.Name };
var q =
this.Collection
.Where(x => x.Age < 20)
.OrderBy(x => x.Name)
.Select(x => new { Code = x.Code, Name = x.Name });
長いので改行されていますが,単にデリゲートを引数としたメソッドを書き連ねているだけです。 各メソッドの引数では,ラムダ式が使われていることがわかります。
次回の予定
今回は,C#3.0の新機能として有名なLINQをご説明しました。 次回は,C#3.0で記述した簡単なサンプルコードと,これをC#2.0に置き換えたコードをご紹介したいと思います。
これによって,実際にどのような場面で新機能が使えるのか,どれだけ省力化できるのかについてをご理解いただきたいと思います。

