web-dev-qa-db-ja.com

多対多/一対多の関係で、ICollectionを使用し、IEnumerableまたはList <T>を使用しないのはなぜですか?

これはチュートリアルでよく見られますが、ナビゲーションプロパティはICollection<T>です。

これはEntity Frameworkの必須要件ですか? IEnumerableを使えますか?

ICollectionList<T>の代わりにIEnumerableを使う主な目的は何ですか?

328
Jan Carlo Viray

通常あなたが選択するものはあなたがアクセスする必要がある方法に依存します。一般的に必要なオブジェクトのリストはIEnumerable<>(MSDN: http://msdn.Microsoft.com/ja-jp/library/system.collections.ienumerable.aspx )です。反復する必要があるオブジェクトのリストについては、ICollection<>(MSDN: http://msdn.Microsoft.com/ja-jp/library/92t2ye13.aspx )を参照してください。反復、変更、ソートなどを行う必要があるオブジェクトのリストについては、modified、List<>を参照してください(全リストについては、ここを参照してください。 .aspx ).

より具体的な観点から言えば、遅延ロードはタイプを選択することで機能するようになります。デフォルトでは、Entity Frameworkのナビゲーションプロパティには変更追跡機能が付属しています。これはプロキシです。動的プロキシをナビゲーションプロパティとして作成するには、仮想型ICollectionを実装する必要があります

関係の「多」端を表すナビゲーションプロパティは、ICollectionを実装する型を返す必要があります。ここで、Tは、関係のもう一方の端にあるオブジェクトの型です。 - POCOプロキシを作成するための要件MSDN

関係の定義と管理の詳細MSDN

402
Travis J

ICollection<T>インターフェースは、項目の追加、項目の削除、またはその他の方法でコレクションを変更する方法を提供しないため、IEnumerable<T>が使用されます。

78
Justin Niessner

List<T>に関するご質問への回答

List<T>はクラスです。インターフェイスを指定すると、より柔軟に実装できます。より良い質問は「なぜIList<T>ではないのですか」です。

その質問に答えるために、IList<T>ICollection<T>:integer indexingに追加したものを考えてみてください。つまり、項目は任意の順序を持​​ち、その順序を参照することで取得できます。大抵の場合、これはおそらく意味がありません。アイテムはおそらく異なるコンテキストでは異なる順序で並べる必要があるからです。

56
phoog

ICollectionとIEnumerableの間には基本的な違いがいくつかあります。

  • IEnumerable - Enumeratorを取得してループを作成するためのGetEnumeratorメソッドのみを含みます。
  • ICollectionには以下のメソッドが含まれています - 追加/削除/含む/カウント/コピー先
  • ICollectionはIEnumerableから継承されます。
  • ICollectionでは、add/removeなどのメソッドを使用してコレクションを変更できます。IEnumerableでも同じことをする自由はありません。

簡単なプログラム:

using System;
using System.Collections;
using System.Collections.Generic;

namespace StackDemo
{
    class Program 
    {
        static void Main(string[] args)
        {
            List<Person> persons = new List<Person>();
            persons.Add(new Person("John",30));
            persons.Add(new Person("Jack", 27));

            ICollection<Person> personCollection = persons;
            IEnumerable<Person> personEnumeration = persons;

            //IEnumeration
            //IEnumration Contains only GetEnumerator method to get Enumerator and make a looping
            foreach (Person p in personEnumeration)
            {                                   
               Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);
            }

            //ICollection
            //ICollection Add/Remove/Contains/Count/CopyTo
            //ICollection is inherited from IEnumerable
            personCollection.Add(new Person("Tim", 10));

            foreach (Person p in personCollection)
            {
                Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);        
            }
            Console.ReadLine();

        }
    }

    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Person(string name,int age)
        {
            this.Name = name;
            this.Age = age;
        }
    }
}
18
Ramakrishnan

私はこのように覚えています:

  1. IEnumerableには1つのメソッドGetEnumerator()があり、これによりコレクション内の値を読み取ることはできますが、書き込むことはできません。列挙子を使用することの複雑さの大部分は、C#のfor eachステートメントによって私たちの面倒を見ています。 IEnumerableにはCurrentという1つのプロパティがあり、これは現在の要素を返します。

  2. ICollectionはIEnumerableを実装し、ほとんどの用途でCountを使用するプロパティをいくつか追加します。 ICollectionの汎用バージョンは、Add()およびRemove()メソッドを実装しています。

  3. IListはIEnumerableとICollectionの両方を実装し、アイテムへの整数インデックスアクセスを追加します(データベースで順序付けが行われるため、通常は必要ありません)。

9
user3918295

ICollectionを使うことの基本的な考えは、ある有限量のデータに読み取り専用でアクセスするためのインターフェースを提供することです。実際には、 ICollection.Count プロパティがあります。 IEnumerableは、論理的なポイント、コンシューマによって明示的に指定された条件、または列挙の終わりまでの間に読み取ったデータの連鎖に適しています。

8
Tigran

ナビゲーションプロパティは通常、レイジーロードなどの特定のEntity Framework機能を利用できるように仮想として定義されます。

ナビゲーションプロパティが(多対多または1対多の関係のように)複数のエンティティを保持できる場合、そのタイプはエントリを追加、削除、および更新できるリスト(ICollectionなど)である必要があります。

https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model asp-net-mvcアプリケーション用

2
LewisAntonio803

私がこれまでにやったことは、私のリポジトリのメソッドで以下のことをする必要があるかどうかに応じてIList<Class>ICollection<Class>またはIEnumerable<Class>を使って内部クラスコレクションを宣言することです:列挙、ソート/順序付け、またはを変更します。オブジェクトを列挙する(そしてソートする)必要があるときは、IEnumerableメソッド内でコレクションを処理するためのtemp List<Class>を作成します。この方法は、コレクションが比較的小さい場合にのみ効果があると思いますが、一般的には良い方法である可能性があります。これがなぜ良い習慣にならないのかについての証拠があるならば、私を訂正してください。

2
yardpenalty

箱の外でロジックを使って/ロジックで考えてみて、質問のこれら3つのインターフェースを明確に理解しましょう。

いくつかのインスタンスのクラスがSystem.Collection.IEnumerableインターフェースを実装する場合、簡単な言葉で言えば、このインスタンスは列挙可能で反復可能であると言えます。つまり、このインスタンスは単一のループでgo/get/pass /このインスタンスに含まれるすべてのアイテムと要素を走査/反復します。

つまり、このインスタンスに含まれるすべてのアイテムと要素を列挙することもできます。

System.Collection.IEnumerableインターフェイスを実装するすべてのクラスは、引数をとらずにSystem.Collections.IEnumeratorインスタンスを返すGetEnumeratorメソッドも実装します。

System.Collections.IEnumeratorインターフェイスのインスタンスは、C++イテレータと非常によく似た動作をします。

あるインスタンスのクラスがSystem.Collection.ICollectionインターフェイスを実装している場合、簡単な言葉で言えば、このインスタンスは何かのコレクションであると言えます。

このインターフェイスの汎用バージョン、つまりSystem.Collection.Generic.ICollectionは、この汎用インターフェイスがコレクション内の物のタイプを明示的に示しているため、より有益です。

これはすべて合理的、合理的、論理的であり、System.Collections.ICollectionインターフェイスがSystem.Collections.IEnumerableインターフェイスを継承することは理にかなっています。理論的にはすべてのコレクションも列挙可能で反復可能であり、理論的にはすべてのアイテムと要素を調べることができるからですすべてのコレクションで。

System.Collections.ICollectionインターフェイスは、変更可能な有限の動的コレクションを表します。つまり、既存のアイテムをコレクションから削除し、新しいコレクションを同じコレクションに追加できます。

これは、System.Collections.ICollectionインターフェイスに「追加」メソッドと「削除」メソッドがある理由を説明しています。

System.Collections.ICollectionインターフェースのインスタンスは有限コレクションであるため、「有限」という言葉は、このインターフェースのすべてのコレクションが常に有限数のアイテムと要素を持つことを意味します。

System.Collections.ICollectionインターフェイスのプロパティCountは、この数を返すことを想定しています。

System.Collections.IEnumerableインターフェイスには、System.Collections.IEnumerableがSystem.Collections.ICollectionインターフェイスにあるこれらのメソッドとプロパティがあるとは意味がないため、System.Collections.ICollectionインターフェイスにあるこれらのメソッドとプロパティはありません。

ロジックはまた、列挙可能で反復可能なインスタンスはすべてコレクションである必要はなく、必ずしも変更可能であるとは限らないことも示しています。

私が変更可能と言うとき、列挙可能で反復可能なものから何かを追加または削除できるとすぐに考えないでください。

たとえば、素数の有限シーケンスを作成したばかりの場合、この素数の有限シーケンスはSystem.Collections.IEnumerableインターフェイスのインスタンスです。これは、この有限シーケンス内のすべての素数を1つのループで処理できるためです。そして、それぞれをコンソールウィンドウまたはスクリーンに印刷するなど、私がそれらのそれぞれでやりたいことを行いますが、この有限の一連の素数はSystem.Collections.ICollectionインターフェースのインスタンスではありません。この素数の有限シーケンスに合成数を追加します。

また、次の反復で、現在の反復の現在の素数に次に近い最も大きな素数を取得したい場合は、この素数の有限シーケンスから存在する素数を削除したくない場合もあります。

また、System.Collections.IEnumerableインターフェイスのGetEnumeratorメソッドで "yield return"を使用してコーディングし、メモリヒープに何も割り当てずに素数を生成してから、ガベージコレクター(GC)を両方に割り当てることもできます。これは明らかにオペレーティングシステムメモリの浪費であり、パフォーマンスを低下させるため、ヒープからこのメモリの割り当てを解除して解放します。

System.Collections.IEnumerableインターフェイスのメソッドとプロパティを呼び出すときではなく、System.Collections.IEnumerableインターフェイスのメソッドとプロパティを呼び出すときに、ヒープの動的メモリ割り当てと割り当て解除を行う必要があります(ただし、System.Collections.IEnumerableインターフェイスは1メソッドと0プロパティ)。

このStack Overflow Webページで他の人が言ったことによると、System.Collections.IListインターフェースは単にorderableコレクションを表し、これはSystem.Collections.IListインターフェースのメソッドがインデックスと連携する理由を説明します。 System.Collections.ICollectionインターフェイス。

要するに、System.Collections.ICollectionインターフェイスは、そのインスタンスが順序付け可能であることを意味しませんが、System.Collections.IListインターフェイスはそれを意味します。

理論的に順序付けられたセットは、順序付けられていないセットの特殊なケースです。

これも理にかなっており、System.Collections.IListインターフェイスがSystem.Collections.ICollectionインターフェイスを継承する理由を説明しています。

0
user11336341