Diferença entre várias interfaces genéricas de coleção em C #

11

Estou brincando com o C # para desenvolvimento em Windows e ASP.net MVC há algum tempo. Mas ainda não estou claro em algumas áreas. Estou tentando entender a diferença básica entre e problemas de desempenho com o uso e a troca de tipos semelhantes de interfaces de coleção genérica .

Qual é a diferença básica entre IEnumerable<T>, ICollection<T>, List<T>(Class)?

Eu pareço usá-los e trocá-los sem ver nenhum problema em meus aplicativos. Além disso, existem coleções genéricas semelhantes a essas que podem ser trocadas com as três?

Pankaj Upadhyay
fonte
2
também há IList <T>
jk.

Respostas:

19

Lista <T> é uma classe e implementa as interfaces ICollection <T> e IEnumerable <T> . Além disso, ICollection <T> estende a interface IEnumerable <T>. Eles não são intercambiáveis, pelo menos não de todos os pontos de vista.

Se você possui uma Lista <T>, é garantido que este objeto implemente métodos e propriedades que devem ser implementados pelas interfaces ICollection <T> e IEnumerable <T>. O compilador sabe disso e você pode convertê-los "para baixo" em um ICollection <T> ou em um IEnumerable <T> implicitamente. No entanto, se você tiver uma ICollection <T>, deverá verificar explicitamente em seu código primeiro se é uma Lista <T> ou outra coisa, talvez um Dicionário <T> (onde T é um KeyValuePair ) antes de convertê-lo para o que você deseja. desejo.

Você sabe que o ICollection estende IEnumerable, para que você possa convertê-lo em um IEnumerable. Mas se você tiver apenas um IEnumerable, novamente não há garantia de que seja uma lista. Pode ser, mas poderia ser outra coisa. Você deve esperar uma exceção de conversão inválida se tentar converter uma Lista <T> em um Dicionário <T>, por exemplo.

Portanto, eles não são "intercambiáveis".

Além disso, existem muitas interfaces genéricas, confira o que você pode encontrar no espaço para nome System.Collections.Generic .

Editar: em relação ao seu comentário, não há absolutamente nenhuma penalidade no desempenho se você usar a Lista <T> ou uma das interfaces implementadas. Você ainda precisará criar um novo objeto, confira o seguinte código:

List<T> list = new List<T>();
ICollection<T> myColl = list;
IEnumerable<T> myEnum = list;

list , myColl e myEnum apontam para o mesmo objeto. Se você o declara como uma Lista ou um ICollection ou um IEnumerable, ainda estou exigindo que o programa crie uma Lista. Eu poderia ter escrito isso:

ICollection<T> myColl = new List<T>();

myColl , em tempo de execução ainda é uma lista.

No entanto , este é o ponto mais importante ... para reduzir o acoplamento e aumentar a manutenção, você sempre deve declarar suas variáveis ​​e parâmetros de método usando o menor denominador possível, seja uma interface ou uma classe abstrata ou concreta.

Imagine que a única coisa que o método "PerformOperation" precisa é enumerar elementos, fazer algum trabalho e sair; nesse caso, você não precisa dos cem métodos disponíveis na Lista <T>, você só precisa do que está disponível no IEnumerable <T >, portanto, o seguinte deve ser aplicado:

public void PerformOperation(IEnumerable<T> myEnumeration) { ... }

Ao fazer isso, você e outros desenvolvedores sabem que qualquer objeto de uma classe que implemente a interface IEnumerable <T> pode ser atribuído a esse método. Pode ser uma classe de lista, dicionário ou coleção personalizada que outro desenvolvedor escreveu.

Se, pelo contrário, você especificar que precisa explicitamente de uma Lista concreta <T> (e, embora raramente aconteça na vida real, isso ainda pode acontecer), você e outros desenvolvedores sabem que deve ser uma Lista ou outra classe concreta herdando da lista.

Jalayn
fonte
Antes de tudo, obrigado. Agora, o ponto de preocupação é como decidir qual usar ??. Como a List <T> implementa as duas interfaces, por que nem sempre a usa em todos os locais em que IEnumerable ou ICollection é necessário. Sempre usar a lista terá um impacto no desempenho? Por favor edite sua resposta para responder a estas preocupações
Pankaj Upadhyay
Eu editei para responder suas perguntas de desempenho
Jalayn
+1, mas eu acrescentaria que, nos raros casos em que você realmente precisa passar uma lista para um método, você deve usar IListem vez Listda declaração do método.
28913 Konamiman
@ Konamiman - Depende se você precisar de List<>funcionalidades específicas, como .AddRange(). O IList<>não expõe isso.
Bobson
6

Dê uma olhada nas páginas do MSDN para ICollection e IEnumerable .

Em termos muito abstratos, é assim que concebo esses tipos.

Um IEnumerable é qualquer coisa que possa ser enumerada - ou seja, iterada. Não significa necessariamente uma 'coleção'; por exemplo, um IQueryable implementa IEnumerable e não é uma coleção, mas é algo que pode ser consultado para retornar objetos. Para implementar IEnumerable, um objeto precisa apenas retornar um objeto quando consultado. Posso dizer que tenho inúmeras tarefas que vou fazer hoje (não é uma lista porque não a escrevi nem a formulei, mas posso dizer o que vou fazer agora e se você perguntasse 'e depois?', eu seria capaz de lhe dizer a seguinte tarefa).

Uma ICollection é mais concreta que uma IEnumerable. A principal diferença é que uma coleção sabe quantos itens ela contém; para descobrir quantos itens há em um Enumerable, você efetivamente percorre e os conta:

Eu: Pessoal, quantos itens você tem em você?

Enumerável: eu realmente não sei. Bem, aqui está um item. Eu tenho outro, então são dois. E outro, então são três ... e outro ... ok, então são 2382. Chega de itens, então eu tenho 2382. Não me pergunte novamente, porque vou ter que passar por todos eles novamente.

Coleção: Eu tenho 2382 itens. Eu já sei disso.

Uma coleção é geralmente algo que já sabe onde estão todos os seus elementos e não precisa ir e encontrá-los ou gerá-los quando você os solicita. É mais ... concreto que um Enumerável.

Na minha opinião, a diferença entre um Enumerable e uma Collection é muito maior que a diferença entre uma Collection e uma List. Na verdade, estou lutando para pensar em uma diferença prática entre uma coleção e uma lista, mas acredito que a lista forneça melhores métodos para pesquisar e fazer pedidos.

Outros tipos de coleção incluem Queuee Stack, assim como Dictionary.

Os nomes desses tipos são bastante úteis - você pode conceber uma fila e uma pilha como suas contrapartes no mundo real e considerar as diferenças que você pode ter em uma lista.

Kirk Broadhurst
fonte
"Estou lutando para pensar em uma diferença prática entre uma coleção e uma lista" ... Mais tarde, em sua resposta, você mesmo responde. Um Listé um ICollection, mas um ICollectionnão é sempre um List( Queue, Stack, Dictionary, ...)
Steven Jeuris
@ Steven É uma resposta muito desmedida. Concordo que essa é uma diferença importante, mas não diria que é uma diferença prática. O que isso significa para o usuário?
precisa
Isso é fácil! :) Queue<int> queue = (Queue<int>)list;lançará um InvalidCastExceptionquando listnão for um Queue<int>. A diferença entre fila e lista está fora do escopo desta pergunta.
Steven Jeuris
Não é o aspecto crítico do IEnumerable que ele pode retornar os itens atuais e os próximos - você meio que alude a isso, mas não o diz explicitamente. Essencialmente, algo que implementa o IEnumerable sozinho não pode retornar um item arbitrário de seus membros quando consultados - apenas o atual e o próximo.
Cori
@ori Essa é uma maneira muito sucinta de colocar isso, muito mais clara que a minha resposta.
usar o seguinte
-1

IQueryable:

a consulta não é executada até que realmente itere sobre os itens, talvez fazendo um .ToList ()

IEnumerable:

lista de itens somente para a frente. Você não pode chegar ao "item 4" sem passar os itens 0-3. lista somente leitura, você não pode adicionar ou remover a ela. Ainda pode usar a execução adiada.

IList:

acesso aleatório à lista completa inteiramente na memória suporta a adição e remoção

ICollection:

Está entre IEnumerable e IList. O que é "melhor" depende dos seus requisitos. Geralmente, embora um IEnumerable seja "bom o suficiente" se você deseja exibir apenas itens. Pelo menos sempre use a variante genérica.

Zia Qammar
fonte
esta resposta não parece acrescentar nada valiosa sobre o que já foi publicado em respostas anteriores
mosquito
é apenas um conceito simples sobre tudo
Zia Qammar