Zazwyczaj to, co wybierzesz, będzie zależeć od metod, do których potrzebujesz dostępu. Ogólnie - IEnumerable<>
(MSDN: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx ), aby uzyskać listę obiektów, które wymagają jedynie iteracji, ICollection<>
(MSDN: http: // msdn.microsoft.com/en-us/library/92t2ye13.aspx ), aby uzyskać listę obiektów, które należy iterować i modyfikować, List<>
oraz listę obiektów, które należy iterować, modyfikować, sortować itp. (patrz tutaj pełna lista: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx ).
Z bardziej szczegółowego punktu widzenia leniwe ładowanie odgrywa rolę przy wybieraniu typu. Domyślnie właściwości nawigacji w Entity Framework są dostarczane ze śledzeniem zmian i są serwerami proxy. Aby dynamiczny serwer proxy mógł zostać utworzony jako właściwość nawigacji, typ wirtualny musi zostać zaimplementowany ICollection
.
Właściwość nawigacji, która reprezentuje „wiele” końca relacji, musi zwracać typ, który implementuje ICollection, gdzie T jest typem obiektu na drugim końcu relacji. - Wymagania dotyczące tworzenia proxy POCO MSDN
Więcej informacji o definiowaniu i zarządzaniu relacjami MSDN
List
powinno być o wiele lepiej, tak?List
. Chociaż ma największy narzut, zapewnia największą funkcjonalność.private IEnumerable<int> _integers = new List<int> { 1, 2, 3 };
używa tej samej pamięci coprivate List<int> _integers = new List<int> { 1, 2, 3 };
List<T>
maGetEnumerator()
niezależną od implementacji metodęIEnumerable<T>
, która zwraca zmienną strukturę typuList<T>.Enumerator
. W większości kontekstów ten typ przyniesie nieco lepszą wydajność niż autonomiczny obiekt sterty. Kompilatory, które wyliczają typu kaczego (tak jak C # i vb.net) mogą skorzystać z tego podczas generowaniaforeach
kodu. JeśliList<T>
rzutowanieIEnumrable<T>
nastąpi przedforeach
,IEnumerable<T>.GetEnumerator()
metoda zwróci obiekt przydzielony do sterty, uniemożliwiając optymalizację.ICollection<T>
jest używany, ponieważIEnumerable<T>
interfejs nie umożliwia dodawania elementów, usuwania elementów ani modyfikowania kolekcji w inny sposób.źródło
List<T>
wdrażaICollection<T>
.ICollection
, nie pozwala w żaden sposób dodawać elementów, ale nadal jest przydatnym dodatkiem,IEnumerable<T>
ponieważ zapewniaCount
członka, który jest zwykle znacznie szybszy niż wyliczanie wszystkiego. Zauważ, że jeśli doIList<Cat>
lubICollection<Cat>
kod zostanie przekazany w oczekiwaniu naIEnumerable<Animal>
,Count()
metoda rozszerzenia będzie szybka, jeśli zaimplementuje ona nie-rodzajoweICollection
, ale nie, jeśli zaimplementuje tylko ogólne interfejsy, ponieważ typoweICollection<Cat>
nie zostanie zaimplementowaneICollection<Animal>
.Odpowiadając na twoje pytanie dotyczące
List<T>
:List<T>
jest klasą; określenie interfejsu pozwala na większą elastyczność implementacji. Lepszym pytaniem jest „dlaczego nieIList<T>
?”Aby odpowiedzieć na to pytanie, zastanów się, co
IList<T>
dodaje doICollection<T>
: indeksowanie liczb całkowitych, co oznacza, że elementy mają pewną dowolną kolejność i można je odzyskać przez odniesienie do tej kolejności. Prawdopodobnie nie ma to większego znaczenia w większości przypadków, ponieważ elementy prawdopodobnie trzeba zamówić inaczej w różnych kontekstach.źródło
Istnieją pewne podstawowe różnice między ICollection a IEnumerable
Prosty program:
źródło
Pamiętam to w ten sposób:
IEnumerable ma jedną metodę GetEnumerator (), która pozwala czytać wartości w kolekcji, ale nie zapisywać do niej. Większość złożoności korzystania z modułu wyliczającego zajmuje się dla każdego wyrażenia w języku C #. IEnumerable ma jedną właściwość: Current, która zwraca bieżący element.
ICollection implementuje IEnumerable i dodaje kilka dodatkowych właściwości, z których większość używa Count. Ogólna wersja ICollection implementuje metody Add () i Remove ().
IList implementuje zarówno IEnumerable, jak i ICollection, i dodaje dostęp do indeksowania liczb całkowitych do elementów (co zwykle nie jest wymagane, ponieważ porządkowanie odbywa się w bazie danych).
źródło
Podstawową ideą użycia
ICollection
jest zapewnienie interfejsu umożliwiającego dostęp tylko do odczytu do pewnej skończonej ilości danych. W rzeczywistości masz właściwość ICollection.Count .IEnumerable
jest bardziej odpowiedni dla niektórych łańcuchów danych, w których czytasz do pewnego logicznego punktu, niektórych warunków wyraźnie określonych przez konsumenta lub do końca wyliczenia.źródło
ICollection
jest tylko do odczytu, podczas gdyICollection<T>
nie jest.Właściwości nawigacji są zazwyczaj definiowane jako wirtualne, dzięki czemu mogą korzystać z niektórych funkcji Entity Framework, takich jak leniwe ładowanie.
Jeśli właściwość nawigacji może przechowywać wiele encji (jak w relacjach wiele do wielu lub jeden do wielu), jej typem musi być lista, w której wpisy można dodawać, usuwać i aktualizować, takie jak ICollection.
https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net- aplikacja mvc
źródło
Co mam zrobić w przeszłości jest zadeklarować moje zbiory klasa wewnętrzna użyciu
IList<Class>
,ICollection<Class>
lubIEnumerable<Class>
(jeśli listy statycznej) w zależności od tego, czy nie będę musiał zrobić dowolną liczbę z następujących czynności w metodzie w moim repozytorium: wyliczyć, sortowania / zamówienia lub modyfikowania . Kiedy po prostu muszę wyliczyć (i być może posortować) obiekty, tworzę tempList<Class>
do pracy z kolekcją w ramach metody IEnumerable. Myślę, że ta praktyka byłaby skuteczna tylko wtedy, gdy kolekcja jest stosunkowo niewielka, ale ogólnie może być dobrą praktyką, idk. Proszę mnie poprawić, jeśli istnieją dowody, dlaczego nie jest to dobra praktyka.źródło
Spróbujmy myśleć nieszablonowo za pomocą logiki / i zrozumieć dokładnie te trzy interfejsy w pytaniu:
Gdy klasa niektórych instancji implementuje interfejs System.Collection.IEnumerable, to w prostych słowach możemy powiedzieć, że ta instancja jest zarówno policzalna, jak i iterowalna, co oznacza, że ta instancja pozwala w jakiś sposób w jednej pętli przejść / uzyskać / przekazać / przeglądaj / iteruj po / przez wszystkie elementy i elementy, które zawiera ta instancja.
Oznacza to, że można również wyliczyć wszystkie elementy i elementy, które zawiera ta instancja.
Każda klasa implementująca interfejs System.Collection.IEnumerable implementuje również metodę GetEnumerator, która nie przyjmuje argumentów i zwraca instancję System.Collections.IEnumerator.
Instancje interfejsu System.Collections.IEnumerator zachowują się bardzo podobnie do iteratorów C ++.
Kiedy klasa niektórych instancji implementuje interfejs System.Collection.ICollection, to w prostych słowach możemy powiedzieć, że ta instancja jest zbiorem rzeczy.
Ogólna wersja tego interfejsu, tj. System.Collection.Generic.ICollection, jest bardziej informacyjna, ponieważ ten ogólny interfejs wyraźnie określa, jaki jest typ rzeczy w kolekcji.
Wszystko to jest rozsądne, racjonalne, logiczne i ma sens, że interfejs System.Collections.ICollection dziedziczy po interfejsie System.Collections.IEnumerable, ponieważ teoretycznie każda kolekcja jest zarówno wymienna, jak i iterowalna, a teoretycznie możliwe jest przejrzenie wszystkich elementów i elementów w każdej kolekcji.
Interfejs System.Collections.ICollection reprezentuje skończoną kolekcję dynamiczną, którą można zmieniać, co oznacza, że istniejące elementy można usunąć z kolekcji, a nowe elementy można dodać do tej samej kolekcji.
To wyjaśnia, dlaczego interfejs System.Collections.ICollection ma metody „Dodaj” i „Usuń”.
Ponieważ instancje interfejsu System.Collections.ICollection są kolekcjami skończonymi, słowo „skończone” oznacza, że każda kolekcja tego interfejsu ma zawsze skończoną liczbę elementów i elementów.
Właściwość Count interfejsu System.Collections.ICollection zakłada zwrócenie tej liczby.
Interfejs System.Collections.IEnumerable nie ma tych metod i właściwości, jakie ma interfejs System.Collections.ICollection, ponieważ nie ma sensu, aby System.Collections.IEnumerable miał te metody i właściwości, które ma interfejs System.Collections.ICollection.
Logika mówi również, że każda instancja, która jest zarówno policzalna, jak i iterowalna, niekoniecznie jest kolekcją i niekoniecznie jest zmienna.
Kiedy mówię zmienny, mam na myśli to, że nie od razu myślę, że możesz dodać lub usunąć coś z czegoś, co jest zarówno policzalne, jak i iterowalne.
Na przykład, jeśli właśnie utworzyłem skończoną sekwencję liczb pierwszych, ta skończona sekwencja liczb pierwszych jest rzeczywiście instancją interfejsu System.Collections.IEnumerable, ponieważ teraz mogę przejrzeć wszystkie liczby pierwsze w tej skończonej sekwencji w jednej pętli i rób wszystko, co chcę zrobić z każdym z nich, na przykład drukując każdy z nich do okna lub ekranu konsoli, ale ta skończona sekwencja liczb pierwszych nie jest instancją interfejsu System.Collections.ICollection, ponieważ nie ma sensu dodaj liczby złożone do tej skończonej sekwencji liczb pierwszych.
Również chcesz, aby w następnej iteracji uzyskać następną najbliższą większą liczbę pierwszą do bieżącej liczby pierwszej w bieżącej iteracji, jeśli tak, nie chcesz również usuwać istniejących liczb pierwszych z tej skończonej sekwencji liczb pierwszych.
Prawdopodobnie chcesz także użyć, zakodować i napisać „return return” w metodzie GetEnumerator interfejsu System.Collections.IEnumerable w celu wygenerowania liczb pierwszych i nieprzydzielania niczego na stercie pamięci, a następnie zadania Garbage Collector (GC) do obu zwolnij i zwolnij tę pamięć ze sterty, ponieważ jest to oczywiście zarówno marnowanie pamięci systemu operacyjnego, jak i zmniejszenie wydajności.
Dynamiczne przydzielanie i zwalnianie pamięci na stercie powinno odbywać się podczas wywoływania metod i właściwości interfejsu System.Collections.ICollection, ale nie podczas wywoływania metod i właściwości interfejsu System.Collections.IEnumerable (chociaż interfejs System.Collections.IEnumerable ma tylko 1 metoda i 0 właściwości).
Zgodnie z tym, co powiedzieli inni na tej stronie przepełnienia stosu, interfejs System.Collections.IList po prostu reprezentuje porządek kolekcję do co wyjaśnia, dlaczego metody interfejsu System.Collections.IList działają z indeksami w przeciwieństwie do interfejsu System.Collections.ICollection.
W skrócie interfejs System.Collections.ICollection nie oznacza, że jego instancję można zamówić, ale interfejs System.Collections.IList implikuje to.
Zestaw teoretycznie uporządkowany to specjalny przypadek zestawu nieuporządkowanego.
Ma to również sens i wyjaśnia, dlaczego interfejs System.Collections.IList dziedziczy interfejs System.Collections.ICollection.
źródło