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?
c#
generics
interfaces
Pankaj Upadhyay
fonte
fonte
Respostas:
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 , 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:
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:
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.
fonte
IList
em vezList
da declaração do método.List<>
funcionalidades específicas, como.AddRange()
. OIList<>
não expõe isso.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:
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
Queue
eStack
, assim comoDictionary
.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.
fonte
List
é umICollection
, mas umICollection
não é sempre umList
(Queue
,Stack
,Dictionary
, ...)Queue<int> queue = (Queue<int>)list;
lançará umInvalidCastException
quandolist
não for umQueue<int>
. A diferença entre fila e lista está fora do escopo desta pergunta.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.
fonte