Effective C# 3rd 読書メモ 42 IEnumerableとIQueryableのデータソースを区別する

IQueryableとIEnumerableはとても似たAPIシグネチャをもっている。また、IQueryableはIEnumerableを継承している。この2つのインターフェイスは原則として交換可能である。一方、一連の要素(シーケンス)は交換可能とは限らず、そのふるまいやパフォーマンスも大きく異なる。

以下のコードの最終的な出力はどちらも同じだが、裏側で実行される処理は異なる。

var q =
        from c in dbContext.Customers
        where c.City == "London"
        select c;
var finalAnswer = from c in q
                  orderby c.Name
                  select c;
// Code to iterate the final Answer sequence elided

var q =
    (from c in dbContext.Customers
     where c.City == "London"
     select c).AsEnumerable();
var finalAnswer = from c in q
                  orderby c.Name
                  select c;
// Code to iterate final Answer elided.

前者では、LINQ to SQLライブラリによって2つのLINQを合成してSQLが生成され、SQLが一度だけ実行される。後者では、はじめのLINQから生成されたSQLの実行後、その結果を使用して2番めのLINQがLINQ to Objectsによって実行される。多くの場合、IQueryableのまま使ったほうが、IEnumerableを使うよりもパフォーマンスが良い。

IEnumerableとIQueryableを透過的に扱いたい場合に便利なのがAsQueryable()メソッドである。

public static IEnumerable<Product>
    ValidProducts(this IEnumerable<Product> products) =>
    from p in products.AsQueryable()
    where p.ProductName.LastIndexOf('C') == 0
    select p;

コメントを残す

コメントを残す