Вопрос по c#, entity-framework – Зачем использовать ICollection, а не IEnumerable или List <T> для отношений многие-многие / один-многие?
к каким методам вам нужен доступ. В общем -IEnumerable<>
(MSDN:http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx) для списка объектов, которые нужно только пройти через,ICollection<>
(MSDN:http://msdn.microsoft.com/en-us/library/92t2ye13.aspx) для списка объектов, которые необходимо перебрать и изменить,List<>
для получения списка объектов, которые необходимо перебрать, изменить, отсортировать и т. д. (полный список см. здесь:http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx).
С более конкретной точки зрения, ленивая загрузка играет с выбором типа. По умолчанию свойства навигации в Entity Framework поставляются с отслеживанием изменений и являются прокси-серверами. Чтобы динамический прокси-сервер создавался как свойство навигации, виртуальный типmust воплощать в жизньICollection
.
A navigation property that represents the "many" end of a relationship must return a type that implements ICollection, where T is the type of the object at the other end of the relationship. -Requirements for Creating POCO ProxiesMSDN
Более подробная информация об определении и управлении отношениямиMSDN
List
должно быть намного лучше, да?
private IEnumerable<int> _integers = new List<int> { 1, 2, 3 };
использует ту же память, что иprivate List<int> _integers = new List<int> { 1, 2, 3 };
List
много. Хотя у него больше всего накладных расходов, он обеспечивает большую функциональность.
List<T>
имеетGetEnumerator()
метод, отдельный от его реализацииIEnumerable<T>
, который возвращает изменяемый тип структурыList<T>.Enumerator
, В большинстве случаев этот тип даст немного лучшую производительность, чем автономный объект кучи. Компиляторы, которые используют перечислители утилитарного типа (как это делают и C #, и vb.net), могут использовать это при генерацииforeach
код. ЕслиList<T>
брошен вIEnumrable<T>
передforeach
,IEnumerable<T>.GetEnumerator()
Метод возвращает объект, выделенный в куче, что делает оптимизацию невозможной.
ICollection<T>
используется потому, чтоIEnumerable<T>
Интерфейс не позволяет добавлять элементы, удалять элементы или иным образом изменять коллекцию.
List<T>
инвентарьICollection<T>
.
ICollection
не позволяет каким-либо образом добавлять элементы, но все еще является полезным дополнением кIEnumerable<T>
потому что это обеспечиваетCount
член, который обычно намного быстрее, чем перечислять все. Обратите внимание, что еслиIList<Cat>
или жеICollection<Cat>
передается в код, ожидающийIEnumerable<Animal>
,Count()
метод расширения будет быстрым, если он реализует неуниверсальныйICollection
, но не если он реализует только общие интерфейсы, так как типичныйICollection<Cat>
не будет реализовыватьICollection<Animal>
.
IEnumerable has one method GetEnumerator() which allows one to read through the values in a collection but not write to it. Most of the complexity of using the enumerator is taken care of for us by the for each statement in C#. IEnumerable has one property: Current, which returns the current element.
ICollection implements IEnumerable and adds few additional properties the most use of which is Count. The generic version of ICollection implements the Add() and Remove() methods.
IList implements both IEnumerable and ICollection, and add the integer indexing access to items (which is not usually required, as ordering is done in database).
Простая программа:
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;
}
}
}
List<T>
:
List<T>
это класс; указание интерфейса обеспечивает большую гибкость реализации. Лучший вопрос - почему бы и нет?IList<T>
? & Quot;
Чтобы ответить на этот вопрос, подумайте, чтоIList<T>
добавляет кICollection<T>
: целочисленная индексация, что означает, что элементы имеют некоторый произвольный порядок, и могут быть получены с помощью ссылки на этот порядок. Это, вероятно, не имеет смысла в большинстве случаев, так как предметы, вероятно, должны быть по-разному упорядочены в разных контекстах.
что я сделал в прошлом, это объявил мои коллекции внутренних классов, используяIList<Class>
, ICollection<Class>
или жеIEnumerable<Class>
(если статический список) в зависимости от того, придется ли мне делать какие-либо из следующих действий в методе моего репозитория:enumerate, sort/order or modify, Когда мне просто нужно перечислить (и, возможно, отсортировать) объекты, я создаю временнуюList<Class>
работать с коллекцией в методе IEnumerable. Я думаю, что эта практика будет эффективной только в том случае, если коллекция будет относительно небольшой, но в целом это может быть хорошей практикой, ИДК. Пожалуйста, поправьте меня, если есть доказательства того, почему это не будет хорошей практикой.
чтобы они могли использовать определенные функции Entity Framework, такие как отложенная загрузка.
Если свойство навигации может содержать несколько объектов (как в отношениях «многие ко многим» или «один ко многим»), его тип должен быть списком, в который можно добавлять, удалять и обновлять записи, например ICollection.
ICollection
является интерфейсом для доступа только для чтения к некоторому конечному объему данных. На самом деле у вас естьICollection.Count имущество.IEnumerable
больше подходит для некоторой цепочки данных, где вы читаете до некоторой логической точки, некоторого условия, явно указанного потребителем, или до конца перечисления.
ICollection
только для чтения, покаICollection<T>
не является.