Generics e tipagem em C#: escrevendo código flexível sem copiar e colar

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Generics e tipagem em C#: por que não dá para viver sem eles?



Imagine que você está construindo uma casa, mas toda vez que precisa martelar um prego, você esculpe um novo martelo especialmente para aquele prego. Absurdo? É exatamente assim que o código fica sem generalizações (Generics). Em C#, Generics são aquele martelo universal que serve para qualquer tarefa, mas sem perder a precisão.



Hoje vamos entender como Generics e tipagem em C# transformam seu código de um conjunto de gambiarras desconexas em um sistema organizado, flexível e seguro. Você aprenderá a escrever métodos e classes universais que funcionam com qualquer tipo de dado, mas sem sacrificar o desempenho. Vamos nessa!



O que são Generics e para que servem?



Generics (generalizações) são um mecanismo que permite criar classes, métodos e interfaces que funcionam com qualquer tipo de dado, mas mantendo a tipagem estrita em tempo de compilação. Parece complicado? Na prática, é simples.



Antes dos Generics em C# (versão 2.0, 2005), os desenvolvedores usavam duas abordagens:

  • Copia e cola — criar uma classe separada para cada tipo (int, string, double, etc.).
  • object — usar o tipo base object, o que gerava boxing/unboxing e perda de desempenho.


Ambas as opções são ruins. A primeira perde tempo, a segunda perde desempenho. Generics resolvem os dois problemas de uma vez.



Como os Generics funcionam na prática?



// Sem Generics: copia e cola para cada tipopublic class IntList{    private int[] items = new int[10];    public void Add(int item) { /* ... */ }}

public class StringList{ private string[] items = new string[10]; public void Add(string item) { /* ... */ }}

// Com Generics: uma classe para todos os casospublic class GenericList<T>{ private T[] items = new T[10]; public void Add(T item) { /* ... */ }}

// Usovar intList = new GenericList<int>();var stringList = new GenericList<string>();


Observe: GenericList<T> é um modelo. No lugar de T, você insere qualquer tipo (int, string, sua própria classe), e o compilador cria uma versão específica do código para aquele tipo. Sem duplicação, sem object.



Tipagem em C#: estática, forte, segura



Antes de nos aprofundarmos, lembre-se que C# é uma linguagem com tipagem estática. Isso significa que o tipo de cada variável é determinado em tempo de compilação. Generics não quebram essa regra; pelo contrário, a fortalecem.



Quando você escreve List<int>, o compilador sabe exatamente que dentro da lista há apenas números inteiros. Se tentar adicionar uma string, receberá um erro de compilação, não uma exceção em tempo de execução. Isso é segurança de tipos.



Generics vs object: a batalha do desempenho



// Exemplo ruim com objectArrayList badList = new ArrayList();badList.Add(123);           // Boxing int -> objectint value = (int)badList[0]; // Unboxing object -> int

// Exemplo bom com GenericsList<int> goodList = new List<int>();goodList.Add(123); // Sem boxingint value = goodList[0]; // Sem unboxing


Para tipos por valor (int, double, struct), a diferença de desempenho pode chegar a 10-20 vezes. Para tipos por referência (class), não há boxing, mas Generics ainda ganham por não exigirem conversões de tipo.



Métodos universais: flexibilidade sem código extra



Generics funcionam não apenas com classes, mas também com métodos. Suponha que você precise escrever um método que troque dois elementos de lugar. Sem Generics, você teria que escrever várias sobrecargas:



// Sem Genericspublic void SwapInt(ref int a, ref int b) { int temp = a; a = b; b = temp; }public void SwapString(ref string a, ref string b) { string temp                

Blogs

Book Recommendations