IEnumerable と List - どちらを使うべきか? どのように機能するか? 質問する

IEnumerable と List - どちらを使うべきか? どのように機能するか? 質問する

列挙子と LINQ の動作について疑問があります。次の 2 つの単純な選択を検討してください。

List<Animal> sel = (from animal in Animals 
                    join race in Species
                    on animal.SpeciesKey equals race.SpeciesKey
                    select animal).Distinct().ToList();

または

IEnumerable<Animal> sel = (from animal in Animals 
                           join race in Species
                           on animal.SpeciesKey equals race.SpeciesKey
                           select animal).Distinct();

より一般的な例のように見えるように、元のオブジェクトの名前を変更しました。クエリ自体はそれほど重要ではありません。私が尋ねたいのは次のことです。

foreach (Animal animal in sel) { /*do stuff*/ }
  1. を使用する場合IEnumerable、"sel" (この場合は IEnumerable) をデバッグして検査すると、"inner"、"outer"、"innerKeySelector"、"outerKeySelector" という興味深いメンバーがあることに気付きました。最後の 2 つはデリゲートのようです。"inner" メンバーには "Animal" インスタンスはなく、"Species" インスタンスがあります。これは私にとって非常に奇妙でした。"outer" メンバーには "Animal" インスタンスが含まれています。2 つのデリゲートによって、何が入り、何が出るかが決まるのではないでしょうか。

  2. 「Distinct」を使用すると、「inner」には 6 つの項目が含まれますが (Distinct は 2 つだけなのでこれは誤りです)、「outer」には正しい値が含まれます。おそらく、委任されたメソッドによってこれが決定されますが、これは IEnumerable について私が知っていることより少し多いです。

  3. 最も重要なのは、パフォーマンスの面で 2 つのオプションのうちどちらが優れているかということです。

.ToList()?経由の悪意のあるリスト変換

あるいは列挙子を直接使用することもできますか?

可能であれば、IEnumerable のこの使用法についても少し説明していただくか、リンクをいくつか提供してください。

ベストアンサー1

IEnumerableは動作を記述し、List はその動作の実装です。 を使用するとIEnumerable、コンパイラーに作業を後回しにする機会を与え、その過程で最適化が行われる可能性があります。 ToList() を使用すると、コンパイラーに結果をすぐに具体化するように強制します。

LINQ 式を「積み重ねる」ときは常に を使用しますIEnumerable。これは、動作を指定するだけで、LINQ に評価を延期する機会を与え、プログラムを最適化する可能性があるためです。LINQ は、データベースを列挙するまで、データベースを照会するための SQL を生成しないことを覚えていますか? 次のことを考慮してください。

public IEnumerable<Animals> AllSpotted()
{
    return from a in Zoo.Animals
           where a.coat.HasSpots == true
           select a;
}

public IEnumerable<Animals> Feline(IEnumerable<Animals> sample)
{
    return from a in sample
           where a.race.Family == "Felidae"
           select a;
}

public IEnumerable<Animals> Canine(IEnumerable<Animals> sample)
{
    return from a in sample
           where a.race.Family == "Canidae"
           select a;
}

これで、初期サンプル ("AllSpotted") といくつかのフィルターを選択するメソッドができました。これで、次の操作を実行できます。

var Leopards = Feline(AllSpotted());
var Hyenas = Canine(AllSpotted());

では、 よりも List を使用する方が高速なのでしょうかIEnumerable? クエリが複数回実行されるのを防ぎたい場合のみです。しかし、全体的に優れているのでしょうか? 上の例では、Leopard と Hyena はそれぞれ単一の SQL クエリに変換され、データベースは関連する行のみを返します。しかし、 から List を返した場合AllSpotted()、データベースは実際に必要な量よりもはるかに多くのデータを返す可能性があるため、実行速度が遅くなる可能性があります。また、クライアントでフィルタリングを行うサイクルが無駄になります。

プログラムでは、クエリをリストに変換するのを最後まで延期する方がよい場合があります。そのため、Leopards と Hyenas を複数回列挙する場合は、次のようにします。

List<Animals> Leopards = Feline(AllSpotted()).ToList();
List<Animals> Hyenas = Canine(AllSpotted()).ToList();

おすすめ記事