Od jakiegoś czasu gram z C # dla Windows i ASP.net MVC. Ale nadal jestem niejasny w kilku obszarach. Próbuję zrozumieć podstawową różnicę między problemami z wydajnością a używaniem i zamianą podobnych rodzajów Ogólnych interfejsów kolekcji .
Jaka jest podstawowa różnica między IEnumerable<T>
, ICollection<T>
, List<T>(Class)
?
Wydaje mi się, że używam ich i wymieniam, nie widząc żadnych problemów w moich aplikacjach. Czy istnieją jeszcze podobne ogólne zbiory, które można wymienić na te trzy?
c#
generics
interfaces
Pankaj Upadhyay
źródło
źródło
Odpowiedzi:
Lista <T> jest klasą i implementuje zarówno interfejs ICollection <T>, jak i IEnumerable <T> . Ponadto ICollection <T> rozszerza interfejs IEnumerable <T>. Nie są one wymienne, przynajmniej nie ze wszystkich punktów widzenia.
Jeśli masz List <T>, masz gwarancję, że ten obiekt implementuje metody i właściwości wymagane do zaimplementowania przez interfejs ICollection <T> i IEnumerable <T>. Kompilator wie o tym i możesz niejawnie rzutować je „na ICollection <T> lub IEnumerable <T>. Jeśli jednak masz ICollection <T>, musisz najpierw wyraźnie sprawdzić w kodzie, czy jest to List <T>, czy coś innego, być może Słownik <T> (gdzie T to KeyValuePair ) przed rzutowaniem go na to, co pragnienie.
Wiesz, że ICollection rozszerza IEnumerable, więc możesz przerzucić go na IEnumerable. Ale jeśli masz tylko IEnumerable, ponownie nie masz gwarancji, że jest to lista. Być może, ale może być coś innego. Powinieneś spodziewać się niepoprawnego wyjątku rzutowania, jeśli spróbujesz na przykład rzucić Listę <T> na Słownik <T>.
Nie są więc „wymienne”.
Ponadto istnieje wiele ogólnych interfejsów, sprawdź, co można znaleźć w przestrzeni nazw System.Collections.Generic .
Edycja: jeśli chodzi o twój komentarz, absolutnie nie ma ograniczenia wydajności, jeśli używasz List <T> lub jednego z interfejsów, które implementuje. Nadal będziesz musiał utworzyć nowy obiekt, sprawdź następujący kod:
List , myColl i myEnum wszystkie wskazują na ten sam obiekt. Niezależnie od tego, czy zadeklarujesz go jako List, ICollection, czy IEnumerable, nadal wymagam od programu utworzenia Listy. Mógłbym napisać to:
myColl , w czasie wykonywania jest nadal listą.
Jednakże , to najważniejszy punkt ... aby ograniczyć powstawanie i wzrost konserwacji należy zawsze deklarować zmienne i parametry Metoda z zastosowaniem najniższą możliwą mianownik możliwe dla ciebie, czy jest to interfejs lub abstrakcyjne lub betonu klasy.
Wyobraź sobie, że jedyną rzeczą, której potrzebuje metoda „PerformOperation”, jest wyliczenie elementów, wykonanie pracy i wyjście, w takim przypadku nie potrzebujesz stu dodatkowych metod dostępnych na liście <T>, potrzebujesz tylko tego, co jest dostępne w IEnumerable <T >, więc powinny mieć zastosowanie następujące zasady:
W ten sposób ty i inni programiści wiecie, że dowolny obiekt klasy implementujący interfejs IEnumerable <T> może zostać przekazany tej metodzie. Może to być lista, słownik lub niestandardowa klasa kolekcji, którą napisał inny programista.
Jeśli wręcz przeciwnie, wyraźnie zaznaczysz, że potrzebujesz konkretnej Listy <T> (i chociaż w rzeczywistości tak rzadko się zdarza, może się zdarzyć), Ty i inni programiści wiecie, że musi to być Lista lub inna dziedzicząca klasa z listy.
źródło
IList
raczej niżList
w deklaracji metody.List<>
określonych funkcji, takich jak.AddRange()
.IList<>
Nie narażać tego.Zajrzyj na strony MSDN dla ICollection i IEnumerable .
Mówiąc bardzo abstrakcyjnie, tak wyobrażam sobie te typy.
IEnumerable to wszystko, co można wyliczyć - to znaczy iterować. Nie musi to oznaczać „kolekcji”; na przykład IQueryable implementuje IEnumerable i nie jest kolekcją, ale jest czymś, co można zapytać o zwracane obiekty. Aby zaimplementować IEnumerable, obiekt musi mieć możliwość zwrócenia obiektu po zapytaniu. Mógłbym powiedzieć, że mam Wyliczenie zadań, które zamierzam dzisiaj wykonać (nie jest to lista, ponieważ nie spisałem jej ani nie sformułowałem, ale mogę powiedzieć, co mam teraz zrobić, i jeśli zapytałeś „a potem?”, mógłbym powiedzieć następujące zadanie).
ICollection jest bardziej konkretny niż IEnumerable. Kluczową różnicą jest to, że Kolekcja wie, ile zawiera przedmiotów; aby obliczyć, ile przedmiotów znajduje się w Wyliczaczu, efektywnie przeglądasz i policz je:
Kolekcja jest zwykle czymś, co już wie, gdzie znajdują się wszystkie jej elementy i nie trzeba jej szukać ani generować, gdy o nią poprosisz. Jest bardziej ... konkretny niż Enumerable.
Moim zdaniem różnica między Enumerable a Collection jest znacznie większa niż różnica między Collection a List. W rzeczywistości staram się wymyślić praktyczną różnicę między kolekcją a listą, ale uważam, że lista zapewnia lepsze metody wyszukiwania i porządkowania.
Inne rodzaje kolekcji to
Queue
iStack
, jak równieżDictionary
.Nazwy tego typu są bardzo przydatne - możesz wyobrazić sobie kolejkę i stos jako ich odpowiedniki w świecie rzeczywistym i rozważyć różnice, jakie możesz mieć względem Listy.
źródło
List
JestICollection
, aleICollection
nie zawsze jestList
(Queue
,Stack
,Dictionary
, ...)Queue<int> queue = (Queue<int>)list;
rzuciInvalidCastException
kiedylist
nie jestQueue<int>
. Różnica między kolejką a listą jest poza zakresem tego pytania.IQueryable:
kwerenda nie jest wykonywana, dopóki nie zostanie wykonana iteracja elementów, być może przez wykonanie funkcji .ToList ()
IEnumerable:
lista elementów tylko do przodu. Nie można dostać się do „przedmiotu 4” bez podania przedmiotów 0-3. lista tylko do odczytu, nie można do niej dodawać ani usuwać. Nadal może korzystać z odroczonego wykonania.
IList:
losowy dostęp do pełnej listy całkowicie w pamięci obsługuje dodawanie i usuwanie
ICollection:
Jest między IEnumerable i IList. To, co jest „najlepsze”, zależy od twoich wymagań. Zazwyczaj jednak IEnumerable jest „wystarczająco dobry”, jeśli chcesz tylko wyświetlać elementy. Przynajmniej zawsze używaj wariantu ogólnego.
źródło