Eu vejo isso muito nos tutoriais, com propriedades de navegação como ICollection<T>
.
Esse é um requisito obrigatório para o Entity Framework? Posso usar IEnumerable
?
Qual é o principal objetivo de usar em ICollection
vez de IEnumerable
ou mesmo List<T>
?
fonte
List
deveria ser muito melhor, né?List
muito. Embora tenha a maior sobrecarga, fornece a maior funcionalidade.private IEnumerable<int> _integers = new List<int> { 1, 2, 3 };
usa a mesma memóriaprivate List<int> _integers = new List<int> { 1, 2, 3 };
List<T>
possui umGetEnumerator()
método, separado de sua implementação deIEnumerable<T>
, que retorna um tipo de estrutura mutávelList<T>.Enumerator
. Na maioria dos contextos, esse tipo produzirá um desempenho um pouco melhor do que um objeto de heap independente. Compiladores que enumeradores do tipo pato (como C # e vb.net fazem) podem tirar proveito disso ao gerarforeach
código. SeList<T>
for convertido paraIEnumrable<T>
antes deforeach
, oIEnumerable<T>.GetEnumerator()
método retornará um objeto alocado para heap, impossibilitando a otimização.ICollection<T>
é usado porque aIEnumerable<T>
interface não oferece nenhuma maneira de adicionar itens, remover itens ou modificar a coleção.fonte
List<T>
implementaICollection<T>
.ICollection
não permite adicionar itens, mas ainda é um complemento útil,IEnumerable<T>
pois fornece umCount
membro que normalmente é muito mais rápido do que enumerar tudo. Observe que se umIList<Cat>
ouICollection<Cat>
for passado para o código esperando umIEnumerable<Animal>
, oCount()
método de extensão será rápido se implementar o não genéricoICollection
, mas não se implementar apenas as interfaces genéricas, pois um típicoICollection<Cat>
não será implementadoICollection<Animal>
.Respondendo à sua pergunta sobre
List<T>
:List<T>
é uma classe; especificar uma interface permite mais flexibilidade de implementação. Uma pergunta melhor é "por que nãoIList<T>
?"Para responder a essa pergunta, considere o que
IList<T>
contribui paraICollection<T>
: indexação inteira, o que significa que os itens têm alguma ordem arbitrária e podem ser recuperados por referência a essa ordem. Provavelmente, isso não é significativo na maioria dos casos, pois os itens provavelmente precisam ser pedidos de maneira diferente em contextos diferentes.fonte
Existem algumas diferenças básicas entre ICollection e IEnumerable
Programa Simples:
fonte
Lembro-me assim:
IEnumerable possui um método GetEnumerator () que permite ler os valores em uma coleção, mas não gravar nele. A maior parte da complexidade do uso do enumerador é resolvida pela instrução for for each em C #. IEnumerable possui uma propriedade: Current, que retorna o elemento atual.
ICollection implementa IEnumerable e adiciona poucas propriedades adicionais, das quais a maioria é usada Count. A versão genérica do ICollection implementa os métodos Add () e Remove ().
O IList implementa IEnumerable e ICollection e adiciona o acesso de indexação inteira aos itens (o que geralmente não é necessário, pois a encomenda é feita no banco de dados).
fonte
A idéia básica do uso
ICollection
é fornecer uma interface para acessar apenas uma quantidade finita de dados. Na verdade, você tem uma propriedade ICollection.Count .IEnumerable
é mais adequado para alguma cadeia de dados em que você lê até algum ponto lógico, alguma condição especificada explicitamente pelo consumidor ou até o final da enumeração.fonte
ICollection
é somente leitura enquantoICollection<T>
não é.As propriedades de navegação são normalmente definidas como virtuais, para que possam tirar proveito de determinadas funcionalidades do Entity Framework, como carregamento lento.
Se uma propriedade de navegação puder conter várias entidades (como em relacionamentos muitos para muitos ou um para muitos), seu tipo deverá ser uma lista na qual as entradas possam ser adicionadas, excluídas e atualizadas, como 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- mvc-application
fonte
O que eu fiz no passado é declarar minhas coleções de classes internas usando
IList<Class>
,ICollection<Class>
ouIEnumerable<Class>
(se estática), dependendo se devo ou não fazer qualquer número do seguinte em um método no meu repositório: enumerar, classificar / ordenar ou modificar . Quando só preciso enumerar (e talvez classificar) objetos, crio um tempList<Class>
para trabalhar com a coleção dentro de um método IEnumerable. Eu acho que essa prática só seria eficaz se a coleção for relativamente pequena, mas pode ser uma boa prática em geral, idk. Corrija-me se houver evidências de por que isso não seria uma boa prática.fonte
Vamos tentar pensar fora da caixa com / pela lógica e entender claramente essas três interfaces na sua pergunta:
Quando a classe de alguma instância implementa a interface System.Collection.IEnumerable, então, em palavras simples, podemos dizer que essa instância é enumerável e iterável, o que significa que essa instância permite de alguma forma em um único loop ir / obter / passar / percorra / itere sobre / através de todos os itens e elementos que esta instância contém.
Isso significa que também é possível enumerar todos os itens e elementos que esta instância contém.
Toda classe que implementa a interface System.Collection.IEnumerable também implementa o método GetEnumerator que não usa argumentos e retorna uma instância de System.Collections.IEnumerator.
Instâncias da interface System.Collections.IEnumerator se comportam muito semelhantes aos iteradores do C ++.
Quando a classe de alguma instância implementa a interface System.Collection.ICollection, em palavras simples, podemos dizer que essa instância é uma coleção de coisas.
A versão genérica dessa interface, ou seja, System.Collection.Generic.ICollection, é mais informativa porque essa interface genérica declara explicitamente qual é o tipo de itens na coleção.
Tudo isso é razoável, racional, lógico e faz sentido que a interface System.Collections.ICollection herda da interface System.Collections.IEnumerable, porque teoricamente toda coleção também é enumerável e iterável e, teoricamente, é possível passar por todos os itens e elementos em toda coleção.
A interface System.Collections.ICollection representa uma coleção dinâmica finita que pode ser alterada, o que significa que os itens existentes podem ser removidos da coleção e novos itens podem ser adicionados à mesma coleção.
Isso explica por que a interface System.Collections.ICollection possui os métodos "Adicionar" e "Remover".
Como essas instâncias da interface System.Collections.ICollection são coleções finitas, a palavra "finito" implica que toda coleção dessa interface sempre possui um número finito de itens e elementos.
A propriedade Count da interface System.Collections.ICollection supõe retornar esse número.
A interface System.Collections.IEnumerable não possui esses métodos e propriedades que a interface System.Collections.ICollection possui, porque não faz sentido que System.Collections.IEnumerable tenha esses métodos e propriedades que a interface System.Collections.ICollection possui.
A lógica também diz que toda instância que é enumerável e iterável não é necessariamente uma coleção e não é necessariamente mutável.
Quando digo mutável, quero dizer que não pense imediatamente que você pode adicionar ou remover algo de algo que é enumerável e iterável.
Se eu apenas criei uma sequência finita de números primos, por exemplo, essa sequência finita de números primos é de fato uma instância da interface System.Collections.IEnumerable, porque agora posso revisar todos os números primos dessa sequência finita em um único loop e faça o que eu quiser com cada um deles, como imprimir cada um deles na janela ou na tela do console, mas essa sequência finita de números primos não é uma instância da interface System.Collections.ICollection, porque isso não faz sentido. adicione números compostos a essa sequência finita de números primos.
Além disso, na próxima iteração você deseja obter o próximo número primo maior e mais próximo do número primo atual na iteração atual. Caso contrário, também não deseja remover os números primos existentes dessa sequência finita de números primos.
Além disso, você provavelmente deseja usar, codificar e escrever "yield return" no método GetEnumerator da interface System.Collections.IEnumerable para produzir os números primos e não alocar nada no heap da memória e depois executar tarefas no Garbage Collector (GC) para ambos. desalocar e liberar essa memória do heap, porque obviamente isso é desperdício de memória do sistema operacional e diminui o desempenho.
A alocação e desalocação dinâmica de memória no heap devem ser feitas ao invocar os métodos e propriedades da interface System.Collections.ICollection, mas não ao invocar os métodos e propriedades da interface System.Collections.IEnumerable (embora a interface System.Collections.IEnumerable tenha apenas 1 método e 0 propriedades).
De acordo com o que outros disseram nesta página do Stack Overflow, a interface System.Collections.IList simplesmente representa um pedido coleção e isso explica por que os métodos da interface System.Collections.IList funcionam com índices em contraste com os da interface System.Collections.ICollection.
Em resumo, a interface System.Collections.ICollection não implica que uma instância dela possa ser solicitada, mas a interface System.Collections.IList implica isso.
Conjunto teórico ordenado é um caso especial de conjunto não ordenado.
Isso também faz sentido e explica por que a interface System.Collections.IList herda a interface System.Collections.ICollection.
fonte