Eu acho que a questão quando usar IEnumerable, ICollection, IList ou List é muito comum e que particularmente eu acredito que seja complicado de entender as vezes. Após algumas pesquisas, pretendo fazer este artigo de modo bem completo para que todas suas dúvidas em relação a isto sejam sanadas!
Antes de compararmos os tipos de agrupamentos que temos na linguagem, acho que é válido aprendermos um pouco sobre cada, pois a pouco tempo eu mesmo não sabia o que eram todos estes tipos. Vamos primeiro dar uma olhada os tipos individuais e mais importante dos seus membros. Em geral, é uma boa idéia, se você quiser decidir que tipo você deve usar em uma situação específica em seu código.
IEnumerable
Antes de tudo, é importante entender que existem duas interfaces diferentes definidas na biblioteca de classes de base em .NET. Há uma interface IEnumerable não-genérica e não há uma interface IEnumerable <T> tipo genérico.
A interface IEnumerable está localizado no namespace System.Collections e contém apenas uma única definição do método. A definição de interface se parece com isso:
public interface IEnumerable { IEnumerator GetEnumerator(); }
O método GetEnumerator deve retornar uma instância de um objeto de uma classe que implementa a interface IEnumerator. Desta vez não vamos aprofundar especificamente na interface IEnumerator, mas se você estiver interessado, por favor visite a documentação oficial do MSDN.
É importante saber que o método foreach da linguagem C # trabalha com todos os tipos que implementam a interface IEnumerable. E em C # podemos trabalhar com objetos que não explicitamente implementam IEnumerable ou IEnumerable <T>, podemos fazer foreach em qualquer coleção. Eu acredito que você tem usado o método foreach muitas vezes e sem se preocupar com a razão por que e como ele trabalhou com esse tipo de maneira simples não é mesmo? 😛
IEnumerable<T>
Agora vamos dar uma olhada na definição da versão genérica e de tipo ‘seguro’ chamado IEnumerable <T>, que está localizado no namespace System.Collections.Generic:
public interface IEnumerable<out T> : IEnumerable { IEnumerator<T> GetEnumerator(); }
Como você pode ver, a interface IEnumerable <T> herda a interface IEnumerable. Portanto, um tipo que implementa IEnumerable <T> também tem de implementar os membros de IEnumerable.
IEnumerable <T> define um único método GetEnumerator que retorna uma instância de um objeto que implementa a interface IEnumerator <T>. Por favor, dê uma olhada na documentação oficial do MSDN se você gostaria de obter mais algumas informações e ficar ainda mais por dentro do assunto.
ICollection
Como você pode imaginar, há também duas versões de ICollection que são System.Collections.ICollection ea versão genérica System.Collections.Generic.ICollection <T>.
Vamos dar uma olhada na definição do tipo ICollection interface:
public interface ICollection : IEnumerable { int Count { get; } bool IsSynchronized { get; } Object SyncRoot { get; } void CopyTo(Array array, int index); }
Viu que já começamos a poder sacar algumas paradas que o C# montou nesse grupo de coleção?
ICollection herda de IEnumerable. Portanto, você tem todos os membros da interface IEnumerable implementado em todas as classes que implementam a interface ICollection.
C# manja dos paranauê!
Não vou entrar muito em detalhes sobre os métodos definidos e propriedades. Eu só quero que você saiba sobre a descrição oficial da documentação da MSDN:
Define o tamanho, os enumeradores, e os métodos de sincronização para todas as coleções não genéricas.
ICollection <T>
Quando olhamos para a versão genérica do ICollection, você vai perceber que ela não é exatamente o mesmo que o equivalente não-genérico, veja:
public interface ICollection<T> : IEnumerable<T>, IEnumerable { int Count { get; } bool IsReadOnly { get; } void Add(T item); void Clear(); bool Contains(T item); void CopyTo(T[] array, int arrayIndex); bool Remove(T item); }
Define métodos para manipular coleções genéricas.
IList
A interface IList tem, naturalmente, uma versão genérica e uma não genérica. Começaremos a olhar para a interface IList não genérica:
public interface IList : ICollection, IEnumerable { bool IsFixedSize { get; } bool IsReadOnly { get; } Object this[int index] { get; set; } int Add(Object value); void Clear(); bool Contains(Object value); int IndexOf(Object value); void Insert(int index, Object value); void Remove(Object value); void RemoveAt(int index); }
IList implementa ICollection e IEnumerable. Além disso, fornece definições de métodos para adicionar e remover elementos e para limpar a coleção. Também fornece métodos para tratar o posicionamento dos elementos dentro do conjunto. Ela também fornece um indexador de objetos para permitir que o usuário acesse a coleção com colchetes como:
lista[index].propriedades ou somente de forma generica como lista[index]
IList
Agora vamos dar uma olhada na versão genérica IList:
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable { T this[int index] { get; set; } int IndexOf(T item); void Insert(int index, T item); void RemoveAt(int index); }
Como mencionamos antes, quando falamos sobre a interface ICollection <T>, existem alguns métodos a mais definidos na interface ICollection <T> do que na interface ICollection. Portanto a lista de membros da interface IList é um pouco menor do que o equivalente a não genérica. Então temos alguns novos métodos para acessar uma coleção com posicionamento específico.
Conclusão
Dê uma olhada na imagem seguinte. Nem todos os membros da interface são exibidos, mas deve ser suficiente para dar uma visão geral sobre todos os tipos que discutimos. Tente associar com conjuntos que você aprendeu quando criança :
E agora? Qual o tipo que você deve usar?
Agora que você já olhou para todas as interfaces em questão , estamos prontos para decidir qual a interface que deve depender em que situação. Geralmente é uma ótima idéia para só depender de coisas que realmente precisa. Vou mostrar-lhe como esta decisão pode ser feito muito facilmente e que você pode esperar para ganhar se você fizer isso .
Acredito que, se você usar um tipo de interface mais “selada” como IEnumerable em vez de IList , você protege o seu código contra alterações significativas . Se você usar o IEnumerable , o instanciador do método que você utiliza, pode fornecer qualquer objeto que implementa a interface IEnumerable . Trata-se de quase todos os tipos de coleção da biblioteca de classes base e muitos tipos personalizados definidos. O código de chamada pode ser alterado no futuro, e seu código não vai quebrar tão facilmente como seria se você tivesse usado ICollection ou pior ainda IList.
Se você usar um tipo de interface mais amplo , como IList, você está mais em perigo de quebrar alterações no código. Se alguém quiser chamar o seu método com um objeto personalizado definido que apenas implementa IEnumerable ele simplesmente não vai funcionar e resultar em um erro de compilação .
Geralmente, você deve sempre usar esse tipo que fornece um contrato para apenas os métodos que você realmente usa.
Recomendação
Se você está agora curioso sobre interfaces, como eles funcionam, como implementá-los por conta própria e como usá-los pode melhorar a sua concepção e, portanto, a qualidade de toda a sua base de código, eu recomendo assistir C # Interfaces por Jeremy Clark em Pluralsight, infelizmente o curso é em inglês, mas você pode acompanhar se tiver o básico domínio da lingua. Ele consegue explicar vários conceitos realmente importantes de uma maneira muito fácil de compreender.
Bom, UFA!
Logo quero postar muito mais sobre este tipo de assunto, onde todo mundo não sabe ao certo, justamente para que eu possa aprender ainda mais compartilhando o pouco que sei com vocês! Obrigado e até a próxima! 🙂
Artigo Original em Inglês : claudiobernasconi.ch
Que tal dar uma passada no nosso Facebook?