IEnumerable, ICollection e IReadOnlyList
ResumoEssas interfaces descrevem "o que dá para fazer" com uma coleção. Expor a mais restrita que atende (ex.:
IEnumerable<T>para só iterar) comunica intenção e evita mutações indesejadas.
1. Objetivos de Aprendizagem#
- Diferenciar as principais interfaces de coleção.
- Escolher o tipo de retorno certo para métodos.
- Entender o impacto na iteração e na mutabilidade.
2. Pré-requisitos#
- Coleções essenciais (tópico 7.1).
3. Conceito#
Hierarquia (simplificada), da mais restrita à mais rica:
IEnumerable<T>: só permite iterar (foreach). Base do LINQ.IReadOnlyCollection<T>: iterar +Count.IReadOnlyList<T>: o anterior + acesso por índice ([i]), somente leitura.ICollection<T>: permite modificar (Add,Remove,Clear).IList<T>: modificar + índice.
O porquê de expor a interface certa: um método que retorna IEnumerable<T> deixa claro "apenas percorra"; retornar List<T> convida o chamador a mutar a coleção interna.
4. Mão na Massa#
4.1. Setup#
dotnet new console -n Catalog.Interfaces
cd Catalog.Interfaces
4.2. Implementação Passo a Passo#
- Retornar
IEnumerable<T>(só leitura/iteração):
public class Catalogo
{
private readonly List<string> _itens = new() { "Mouse", "Teclado" };
// O chamador só pode iterar, não mutar a lista interna
public IReadOnlyList<string> Itens => _itens;
public IEnumerable<string> EmPromocao() =>
_itens.Where(i => i.StartsWith("M"));
}
- Consumo:
var c = new Catalogo();
foreach (var item in c.Itens) // itera
Console.WriteLine(item);
// c.Itens.Add("x"); // NÃO compila: IReadOnlyList não expõe Add
4.3. Executando#
dotnet run
5. Exemplo Completo#
Expor IReadOnlyList<string> Itens protege a lista interna: o mundo externo lê e itera, mas não altera o estado do Catalogo por fora.
6. Boas Práticas e Armadilhas#
| Faça | Evite |
|---|---|
| Retornar a interface mais restrita que atende | Expor List interna e permitir mutação externa |
Aceitar IEnumerable em parâmetros (flexível) | Exigir List sem necessidade |
Materializar com ToList() quando for iterar várias vezes | Reenumerar uma query cara repetidamente |
Atenção
IEnumerable<T>pode ser "preguiçoso" (avaliação adiada). Iterar duas vezes pode reexecutar a consulta — veremos isso no módulo de LINQ.
7. Segurança e Produção#
- Expor coleções somente-leitura evita que outras partes do sistema corrompam o estado interno de um objeto — menos bugs de efeito colateral.
8. Exercícios#
- Fácil: troque um retorno
List<T>porIReadOnlyList<T>. - Médio: escreva um método que aceita
IEnumerable<int>e soma os valores. - Desafio: demonstre uma reenumeração acidental e conserte com
ToList().
9. Resumo#
Prefira a interface mais restrita que atende: IEnumerable<T> para iterar, IReadOnlyList<T> para ler por índice, ICollection/IList quando precisar mutar. Isso comunica intenção e protege o estado interno.
10. Próximos Passos#
Com coleções dominadas, entramos em LINQ para consultá-las.
11. Referências#
- Microsoft Learn — IEnumerable<T>
- Microsoft Learn — Interfaces de coleção
- Microsoft Learn — IReadOnlyList<T>