Generics (`<T>`)
ResumoGenerics permitem escrever classes e métodos que funcionam com qualquer tipo, sem perder segurança de tipos nem cair em boxing. São a base de
List<T>,Task<T>, repositórios genéricos e muito mais.
1. Objetivos de Aprendizagem#
- Criar classes e métodos genéricos.
- Aplicar restrições (
where) a parâmetros de tipo. - Entender por que generics evitam boxing e casts.
2. Pré-requisitos#
- Interfaces (tópico 5.3).
3. Conceito#
Um parâmetro de tipo (T) é um "espaço reservado" preenchido quando você usa a classe/método. O porquê: escrever a lógica uma vez e reutilizá-la com segurança de tipos para qualquer T, sem object (que traria boxing e casts).
Restrições (where) limitam o que T pode ser:
where T : class/struct— referência / valor.where T : new()— deve ter construtor sem parâmetros.where T : IEntidade— deve implementar uma interface.
4. Mão na Massa#
4.1. Setup#
dotnet new console -n Catalog.Generics
cd Catalog.Generics
4.2. Implementação Passo a Passo#
- Método genérico:
T PrimeiroOuPadrao<T>(IEnumerable<T> itens, T padrao)
{
foreach (var item in itens) return item;
return padrao;
}
Console.WriteLine(PrimeiroOuPadrao(new[] { 3, 4 }, 0)); // 3
- Classe genérica com restrição:
public interface IEntidade { Guid Id { get; } }
public class Repositorio<T> where T : IEntidade
{
private readonly List<T> _itens = new();
public void Adicionar(T item) => _itens.Add(item);
public T? PorId(Guid id) => _itens.FirstOrDefault(x => x.Id == id);
}
- Uso:
public record Produto(Guid Id, string Nome) : IEntidade;
var repo = new Repositorio<Produto>();
repo.Adicionar(new Produto(Guid.NewGuid(), "Mouse"));
4.3. Executando#
dotnet run
5. Exemplo Completo#
Repositorio<T> funciona para qualquer entidade que tenha Id, com segurança de tipos total — nenhum cast, nenhum boxing. É o embrião do repositório genérico usado em APIs.
6. Boas Práticas e Armadilhas#
| Faça | Evite |
|---|---|
Usar restrições where para exigir capacidades de T | Cair em object e casts manuais |
Nomear parâmetros de tipo claramente (T, TKey, TEntity) | Generics excessivamente abstratos e ilegíveis |
Notagenerics em .NET preservam o tipo em runtime (diferente do "type erasure" de outras plataformas), o que permite reflexão e evita boxing de value types.
7. Segurança e Produção#
- Código genérico bem restrito reduz duplicação — menos lugares para introduzir bugs e mais fácil de manter.
8. Exercícios#
- Fácil: escreva um método genérico
Trocar<T>(ref T a, ref T b). - Médio: adicione uma restrição
where T : IEntidadea uma classe. - Desafio: implemente um
Cache<TKey, TValue>genérico simples comDictionary.
9. Resumo#
Generics reutilizam lógica para qualquer tipo com segurança e sem boxing; where impõe restrições. São a base de coleções e repositórios do .NET.
10. Próximos Passos#
A seguir, as interfaces que unificam coleções: IEnumerable e afins.
11. Referências#
- Microsoft Learn — Generics
- Microsoft Learn — Restrições de parâmetros de tipo
- Microsoft Learn — Métodos genéricos