web-dev-qa-db-ja.com

IQueryable、ICollection、IList、IDictionaryインターフェイスの違い

IQueryable、ICollection、IList、およびIDictionaryインターフェイスの違いを理解しようとしています。これは、反復、インデックス作成、クエリなどの基本操作でより高速です。

collection、List、Dictionaryなどのクラスは、これらのインターフェイスで開始するのに適しています。これらのクラスをいつ使用する必要がありますか。これらのクラスを他のクラスよりも使用することの基本的な利点。

同様の質問がある他の投稿を読んでみましたが、完全な質問に答えることができませんでした。助けてくれてありがとう。

48
Praneeth

これらのインターフェースはすべてIEnumerableを継承しているので、必ず理解してください。このインターフェイスを使用すると、基本的にforeachステートメントでクラスを使用できます(C#で)。

  • ICollectionは、リストした最も基本的なインターフェースです。これは、Countをサポートする列挙可能なインターフェイスであり、それについてです。
  • IListはICollectionのすべてですが、アイテムの追加と削除、インデックスによるアイテムの取得などもサポートしています。これは、「オブジェクトのリスト」で最もよく使用されるインターフェイスであり、あいまいです。
  • IQueryableは、LINQをサポートする列挙可能なインターフェイスです。 IListからIQueryableをいつでも作成してLINQ to Objectsを使用できますが、LINQ to SQLおよびLINQ to EntitiesのSQLステートメントの遅延実行に使用されるIQueryableもあります。
  • IDictionaryは、一意のキーと値のマッピングであるという意味で、異なる動物です。キー/値のペアを列挙できるという点でも列挙可能ですが、それ以外の場合は、リストされている他のものとは異なる目的を果たします。

これらのそれぞれのMSDNドキュメントはまともですので、理解を締めくくるところから始めましょう。

104
John Bledsoe

上記の@ gunny229の回答にいくつかの問題があることに気付いたため、この記事を書いています。これらの問題については、彼の投稿のコメント欄でも言及しています。その投稿を修正するには、投稿のほぼ全体を書き直さなければならなかったので、自分で作成することを考えました。私はOPの質問全体に応えるつもりはありませんが、LINQ to SQLを使用する場合のIQueryableとIEnumerableの違いを指摘したいと思います。

DB(DDLスクリプト)に次の構造を作成しました。

_CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
_

レコード挿入スクリプト(DMLスクリプト)は次のとおりです。

_INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
_

私の目標は、データベースのEmployeeテーブルから単純に上位2レコードを取得することでした。そこで、データベースのEmployeeテーブルを指すADO.NET Entity Data Modelアイテムをコンソールアプリケーションに追加し、LINQクエリの作成を開始しました。

IQueryableルートのコード

_using (var efContext = new EfTestEntities())
{
    IQueryable<int> employees = from e in efContext.Employees  select e.Salary;
    employees = employees.Take(2);

    foreach (var item in employees)
    {
        Console.WriteLine(item);
    }
}
_

このプログラムの実行を開始したとき、SQL ServerインスタンスでSQL Queryプロファイラーのセッションも開始していました。実行の概要は次のとおりです。

  1. 起動されたクエリの総数:1
  2. クエリテキスト:SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

IQueryableは、データベースサーバー側にTop (2)句を適用するのに十分なほど賢いので、5つのレコードのうち2つだけをネットワーク上に持ってきます。クライアントコンピューター側では、これ以上のメモリ内フィルタリングは一切必要ありません。

IEnumerableルートのコード

_using (var efContext = new EfTestEntities())
{
    IEnumerable<int> employees = from e in efContext.Employees  select e.Salary;
    employees = employees.Take(2);

    foreach (var item in employees)
    {
        Console.WriteLine(item);
    }
}
_

この場合の実行の要約:

  1. 起動されたクエリの総数:1
  2. SQLプロファイラーでキャプチャされたクエリテキスト:_SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]_

これで、IEnumerableSalaryテーブルに存在する5つのレコードすべてを持ってきてから、クライアントコンピューターでメモリ内フィルタリングを実行して、上位2レコードを取得します。そのため、より多くのデータ(この場合は3つの追加レコード)が不必要に有線で転送されました。

3
RBT

IQueryable、IList、IDictionary、ICollectionはIEnumerableインターフェイスを継承します。タイプコレクションのすべてのインターフェイスは、IEnumerableインターフェイスを継承します。

IEnumerableとIQueryableの違いIEnumerable:-型を返すクエリを実行しているときIEnumerable。 IEnumerableは最初に最初のクエリを実行し、そのクエリ用に記述されたサブクエリを実行します。

:-特定の国から上位10の人口レコードを取得する場合、LinQで使用するクエリは

IEnumerable _Population = from s in select select s.population; // First Query _Population = _Population.take(10); // Second Query

ここで、このクエリを実行すると、最初のクエリが最初に実行され、IEnumerableはSQLサーバーからすべての母集団のレコードを取得します。次に、In Processメモリにデータを保存し、次のクエリで上位10個の母集団を実行します。 (SQLサーバーで2回実行されます)。

iQueryableを使用して同じクエリを実行する場合.

IQueryable _Population = from s in India select s.population; // First Query _Population = _Population.take(10); // Second Query

このIQueryableでは、データを取得して最初の10を再度フィルタリングするのではなく、単一のクエリで上位10の人口を取得するという意味で、2つのクエリを同時に実行します(SQLサーバーで1回実行) 。

IQueryableおよびIEnumerableの結論

  1. データベース内のデータに対してクエリを作成している場合は、IQueryableを使用します。
  2. 処理中のデータに対してクエリを実行する場合は、IEnumerableを使用します。 IEnumerableには、GetEnumerator()、Current()、およびMoveNext()というメソッドがあります。
3
gunny 229