Desafio C#

Interface genérica e restrições

Enunciado

Crie uma interface genérica IRepositorio<T> com os métodos Adicionar(T item) e T Obter(int indice). Implemente a classe RepositorioMemoria<T> que armazena os itens em uma lista interna. No Main, crie um repositório de string, adicione "C#" e "Interfaces", e exiba o item de índice 1. Em seguida, crie um repositório de int, adicione 10 e 20, e exiba o item de índice 0.

Requisitos

  • Declarar a interface genérica IRepositorio<T> com os métodos Adicionar(T) e Obter(int).
  • Implementar RepositorioMemoria<T> usando uma List<T> interna.
  • O método Obter deve retornar o item no índice informado.
  • No Main, demonstrar o uso com string e int, exibindo os valores corretos.

Código inicial

using System;
using System.Collections.Generic;

// TODO: declarar IRepositorio<T>

// TODO: implementar RepositorioMemoria<T>

public class Program
{
    public static void Main()
    {
        // TODO: criar repositório de string, adicionar itens e exibir o índice 1
        // TODO: criar repositório de int, adicionar itens e exibir o índice 0
    }
}

Saída esperada

Interfaces
10
Ver dica

Use List<T> para armazenar os itens. O método Obter pode acessar diretamente pelo índice da lista.

Mostrar solução
using System;
using System.Collections.Generic;

// Interface genérica que define um contrato para repositórios
public interface IRepositorio<T>
{
    void Adicionar(T item);
    T Obter(int indice);
}

// Implementação genérica usando lista em memória
public class RepositorioMemoria<T> : IRepositorio<T>
{
    private readonly List<T> _itens = new List<T>();

    public void Adicionar(T item)
    {
        _itens.Add(item);
    }

    public T Obter(int indice)
    {
        return _itens[indice];
    }
}

public class Program
{
    public static void Main()
    {
        // Repositório de strings
        IRepositorio<string> repoString = new RepositorioMemoria<string>();
        repoString.Adicionar("C#");
        repoString.Adicionar("Interfaces");
        Console.WriteLine(repoString.Obter(1)); // Interfaces

        // Repositório de inteiros
        IRepositorio<int> repoInt = new RepositorioMemoria<int>();
        repoInt.Adicionar(10);
        repoInt.Adicionar(20);
        Console.WriteLine(repoInt.Obter(0)); // 10
    }
}

Passo a passo

  1. Declaramos a interface genérica IRepositorio<T> com dois métodos: Adicionar e Obter. O parâmetro T será substituído pelo tipo concreto na implementação.
  2. RepositorioMemoria<T> implementa IRepositorio<T> e mantém uma List<T> privada para armazenar os itens.
  3. O método Adicionar insere o item na lista.
  4. O método Obter retorna o item no índice especificado.
  5. No Main, criamos um repositório de string, adicionamos dois itens e exibimos o índice 1.
  6. Em seguida, criamos um repositório de int, adicionamos dois números e exibimos o índice 0.

Por que funciona

Interfaces genéricas permitem criar contratos reutilizáveis e seguros em termos de tipo. A mesma interface serve para diferentes tipos, e a implementação genérica evita duplicação de código. O polimorfismo é garantido pela interface, e a tipagem forte é mantida pelo parâmetro T.

Erros comuns

  • Esquecer de especificar o tipo genérico na declaração da classe: public class RepositorioMemoria : IRepositorio<T> – erro de compilação.
  • Tentar acessar índice inválido: Obter(5) quando a lista tem menos itens lança ArgumentOutOfRangeException.
  • Não importar System.Collections.Generic para usar List<T> – erro de compilação.

Outra forma de resolver

Poderia-se usar um array fixo, mas a lista oferece flexibilidade. Também é possível adicionar restrições genéricas, como where T : class, se necessário.

Saída esperada

Interfaces
10