C#3.0とLINQ
LtUのこの記事から。
LINQは.NETのクラスに特定のメソッドを用意させることで、
var q = from c in Customers where c.City == "London" select c;
という式を埋め込め実行できるようにするもの(実際はCustomersのWhere、Selectメソッドを呼ぶ)。ほかにvar変数や、lambda形式や、無名構造体などがselect式を書きやすくするために導入されている。
あとはDLinq、XLinqと用意していて、RDBやXMLとも連携しやすくなっているようです。仕様よりも101Samplesをみるのがわかりやすいかも。
内部的にどうなる?
理解のため、仕様書にしたがって上式をメソッド呼び出し表現にすると、
var q = this.Customers.Where(c => c.City == "London").Select(c => c);
となる。さらに推論している型を全部明示的に埋めてみると、
IEnumerable<Customer> q = this.Customers.Where<Customer>(delegate (Customer c) {return c.City == "London";}).Select<Customer, Customer>(delegate (Customer c) { return c;});
となる。そしてさらに、SequenceクラスによるIEnumerableへのstatic importをstatic呼び出しにしたら
IEnumerable<Customer> q = Sequence.Select<Customer, Customer>(Sequence.Where<Customer>(this.Customers, delegate (Customer c) {return c.City == "London";}), delegate (Customer c) { return c;});
となります。C#2.0互換の場合はこのようになるでしょうか。メソッドの型パラメータはすべて推論できそうなのでC#2.0なら以下のでよいかも。
IEnumerable<Customer> q = Sequence.Select(Sequence.Where(this.Customers, delegate (Customer c) {return c.City == "London";}), delegate (Customer c) { return c;});
ちなみにSelectやWhereメソッドは定義上は、
delegate S Func<T, S>(T arg); class Selector { public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) { foreach (T elem in source) { if (predicate(elem)) yield return elem; } } public static IEnumerable<S> Select<T, S>(this IEnumerable<T> source, Func<T, S> selector) { foreach (T elem in source) { yield return selector(elem); } } ... }
らしいです。