Menu
Coddy logo textTech

Generics (Classes e Métodos)

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 42 de 70.

Generics permitem que você escreva classes e métodos que funcionam com qualquer tipo de dado, mantendo a segurança de tipos. Em vez de escrever classes separadas para IntList, StringList e DoubleList, você escreve uma única classe genérica que lida com todos eles.

Uma classe genérica usa um parâmetro de tipo, tipicamente chamado T, envolto em colchetes angulares:

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

// Uso com tipos diferentes
Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

Quando você cria Box<int>, o compilador substitui cada T por int. Isso fornece verificação de tipo em tempo de compilação - você não pode armazenar acidentalmente uma string em uma caixa int.

Métodos genéricos funcionam de forma semelhante, permitindo que um único método opere em diferentes tipos:

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // x=2, y=1

O compilador infere o tipo a partir dos argumentos, então você não precisa escrever Swap<int> explicitamente. Genéricos são a base de coleções como List<T> e Dictionary<TKey, TValue>, permitindo código reutilizável e com segurança de tipos.

challenge icon

Desafio

Fácil

Vamos construir um sistema genérico Storage<T> que pode conter e gerenciar itens de qualquer tipo. Você criará uma classe de contêiner reutilizável que demonstra o poder dos genéricos - escreva uma vez, use com inteiros, strings ou qualquer outro tipo!

Você organizará seu código em dois arquivos:

  • Storage.cs: Crie uma classe genérica Storage<T> no namespace DataStorage. Seu contêiner de armazenamento deve:
    • Ter um array privado do tipo T para conter os itens e uma propriedade Count rastreando quantos itens estão armazenados
    • Aceitar uma capacidade em seu construtor para inicializar o array interno
    • Ter um método Add(T item) que adiciona um item se houver espaço
    • Ter um método Get(int index) que retorna o item no índice especificado
    • Ter um método GetAll() que retorna todos os itens armazenados unidos por ", "
  • Program.cs: Em seu arquivo principal, demonstre sua classe genérica funcionando com dois tipos diferentes. Crie um Storage<int> e um Storage<string>, adicione itens a cada um e mostre que a mesma classe funciona perfeitamente com ambos os tipos.

Você receberá quatro entradas:

  • Primeiro inteiro para armazenar
  • Segundo inteiro para armazenar
  • Primeira string para armazenar
  • Segunda string para armazenar

Crie um armazenamento de inteiros com capacidade 5 e um armazenamento de strings com capacidade 5. Adicione os dois inteiros ao armazenamento de inteiros e as duas strings ao armazenamento de strings.

Imprima a saída neste formato:

Int storage: {GetAll()}
Int count: {Count}
First int: {Get(0)}
String storage: {GetAll()}
String count: {Count}
First string: {Get(0)}

Por exemplo, se as entradas forem 42, 100, Hello, e World, a saída deve ser:

Int storage: 42, 100
Int count: 2
First int: 42
String storage: Hello, World
String count: 2
First string: Hello

Observe como você escreve a classe Storage<T> uma vez, mas ela funciona perfeitamente com int e string - essa é a mágica dos genéricos! O compilador garante a segurança de tipos, então você não pode adicionar acidentalmente uma string ao seu armazenamento de inteiros.

Folha de consulta

Generics permitem que você escreva classes e métodos que funcionam com qualquer tipo de dado, mantendo a segurança de tipos.

Uma classe genérica usa um parâmetro de tipo (geralmente T) entre colchetes angulares:

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

Ao criar uma instância, especifique o tipo para substituir T:

Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

Métodos genéricos permitem que um único método opere em diferentes tipos:

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // O compilador infere o tipo a partir dos argumentos

Generics fornecem verificação de tipo em tempo de compilação e são a base de coleções como List<T> e Dictionary<TKey, TValue>.

Experimente você mesmo

using System;
using DataStorage;

class Program
{
    public static void Main(string[] args)
    {
        // Ler as entradas
        int num1 = Convert.ToInt32(Console.ReadLine());
        int num2 = Convert.ToInt32(Console.ReadLine());
        string str1 = Console.ReadLine();
        string str2 = Console.ReadLine();

        // TODO: Criar um Storage<int> com capacidade 5
        
        // TODO: Adicionar os dois inteiros ao armazenamento de inteiros
        
        // TODO: Criar um Storage<string> com capacidade 5
        
        // TODO: Adicionar as duas strings ao armazenamento de strings
        
        // TODO: Imprimir a saída no formato exigido
        // Int storage: {GetAll()}
        // Int count: {Count}
        // First int: {Get(0)}
        // String storage: {GetAll()}
        // String count: {Count}
        // First string: {Get(0)}
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos