Edited at

【小ネタ】LINQのIEnumerableとIQueryableの違いって何だろう?


最初に

本記事は「Effective C#」で得た知見である、IEnumerable<T>IQueryable<T>の違いについて解説したものとなります。

何番煎じとか知らない。

何となくで理解していたところだったので改めてしっかりと学んでみたいと思います。


LINQプロバイダー

標準クエリ演算子を実装しているライブラリのことをLINQプロバイダーと呼びます。もちろん.NET標準ライブラリではIEnumerable<T>IQueryable<T>の二つのインターフェイスに対して標準クエリ演算子の実装が存在しています。


IEnumerable

IEnumerable内部加工方式を取る場合に使用します。内部加工方式とは、データ全件をどこからか受け取った後、ローカル上でクエリを動作させてデータを加工することを指します。

IEnumerable<T>のクエリ式を実装している(つまり拡張メソッド)のはSystem.Linq.Enumerableになります。拡張メソッド群はLINQ to Objectsとも呼ばれています。.NETのコレクションもほとんどがIEnumerable<T>を実装しています。

↓拡張メソッド一覧(公式)↓

https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.enumerable?view=netframework-4.7.2

IEnumerable<T>の実装メソッドはクエリ式中のラムダ式を関数引数として扱うことができるように、デリゲートを使用しています。

IEnumerableはメモリ内のコレクションを繰り返し処理するのに適しています。


IQueryable

IQueryable外部クエリ方式を取る場合に使用します。外部クエリ方式とは、クエリを外部のサーバーへ投げて、サーバー上でそのクエリを使用してデータを加工してもらい、加工結果だけを受け取ることを指します。

IQueryableIEnumerableを継承しているので互換性はありますが、シーケンス同士にも互換性があるとは限りません

IQueryable<T>のクエリ式を実装しているのはSystem.Linq.Queryableになります。

↓拡張メソッド一覧(公式)↓

https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.queryable?view=netframework-4.7.2

IQueryable<T>のクエリ式はまず式ツリー(expression tree)として処理します。そのあとにSQLへと変換され、サーバー上で実行されます。式ツリーとは、ラムダ式をクエリの動作を表すロジックのデータとして受け取るための機能です。

IQueryableはデータベースなどのデータを処理するのに適しています。


二つの使い分け

IEnumerableはローカル上で実行されるため、処理対象のデータをどこか別の場所から持ってくる必要があります。ここで、サーバ等から全件を貰うなどと言うような通信をすると、非常に多くのデータを転送することになる上に不必要なデータまで貰い、余分な処理も行うためボトルネックとなってしまいます。

データを持っているサーバーがRDBのように、高度なクエリを受け付けてくれる場合は外部クエリ方式(IQueryable)を使用した方が良い性能を得られます。


ところでこの二つのハイブリットに当たるAsEnumerableと言う機能もあるのですが、それはまた別の機会に。


参考