CodeGym /Cursos /C# SELF /Contrato para dicionário: ...

Contrato para dicionário: IDictionary<TKey, TValue>

C# SELF
Nível 28 , Lição 4
Disponível

1. Introdução

Imagina só: tu conseguiu um trampo num laboratório secreto de estudos de gatinhos. Te deram a missão — criar um dicionário eletrônico de gatos, onde pelo nome tu descobre rapidinho a idade, cor e tamanho do rabo do gato. Já tem uma solução pronta — é o Dictionary<string, Cat>. Mas aí o chefe chega e fala que pra umas raças raras o dicionário tem que manter a ordem de inserção, e às vezes ainda remover de um jeito especial.

E se tu precisar escrever um método que aceite qualquer “dicionário de gatos”? Não importa a classe exata — o que importa é que ele suporte as operações básicas de “chave-valor”. É aí que entra a interface IDictionary<TKey, TValue>.

IDictionary<TKey, TValue> é tipo um contrato geral que define o que é um dicionário no .NET. Não é uma classe concreta, é uma interface, ou seja, um conjunto de regras que qualquer dicionário de verdade tem que seguir:

  • Busca rápida pela chave
  • Adicionar e remover pares “chave-valor”
  • Percorrer todos os pares
  • Checar se uma chave existe

Se Java existisse na Idade Média, os cavaleiros dela iam lutar contra dragões com chaves e valores no lugar de espadas. Já os devs de C# só iam implementar IDictionary<TKey, TValue> — e o dragão (ou seja, teu código) tava derrotado.

2. Tabela da interface IDictionary

Bora ver as principais “promessas” (membros) dessa interface:

Membro da interface Tipo Descrição
this[TKey key]
Propriedade Indexador. Permite pegar ou definir o valor associado a uma chave específica. Ao ler: se a chave não existe, lança KeyNotFoundException. Ao escrever: se a chave não existe, adiciona um novo par; se já existe, atualiza o valor. Importante: esse é o jeito mais comum de usar dicionários.
ICollection<TKey> Keys
Propriedade Retorna uma coleção com todas as chaves do dicionário. Dá pra percorrer só as chaves.
ICollection<TValue> Values
Propriedade Retorna uma coleção com todos os valores do dicionário. Dá pra percorrer só os valores.
Add(TKey key, TValue value)
Método Adiciona a chave e valor informados no dicionário. Se a chave já existe, gera ArgumentException.
ContainsKey(TKey key)
Método Verifica se o dicionário tem um elemento com a chave informada. Retorna true se achou; senão — false. Isso é muito útil pra evitar erro quando tu tenta acessar uma chave que não existe pelo indexador.
Remove(TKey key)
Método Remove o elemento com a chave informada do dicionário. Retorna true se achou e removeu; senão — false (tipo, se a chave não existia).
TryGetValue(TKey key, out TValue value)
Método Pega o valor associado à chave informada. Esse é o jeito seguro de pegar um valor quando tu não sabe se a chave existe. Retorna true se achou a chave e value tem o valor certo; senão — false, e value fica com o valor padrão de TValue. Esse método não lança exceção, por isso é super usado na vida real.

3. Principais membros da interface IDictionary<TKey, TValue>

Agora sim, bora pro que interessa! Vamos ver o que tem dentro da interface IDictionary<TKey, TValue> e aprender a usar esse “contrato” no teu código.


public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
{
    TValue this[TKey key] { get; set; } // Indexador pra acessar pela chave
    ICollection<TKey> Keys { get; }
    ICollection<TValue> Values { get; }
    void Add(TKey key, TValue value); // Adiciona um novo par (a chave não pode existir)
    bool ContainsKey(TKey key); // Tem essa chave?
    bool Remove(TKey key); // Remove pela chave
    bool TryGetValue(TKey key, out TValue value); // Pega o valor de forma segura
}

Bora destrinchar os pontos principais:

Indexador [key]

Permite pegar e definir valores pela chave:

dictionary["Barsik"] = new Cat("Barsik", 2);

Propriedades Keys e Values

Permitem pegar a coleção de todas as chaves ou todos os valores do dicionário.

foreach (var name in dictionary.Keys)
{
    Console.WriteLine(name);
}

Métodos Add, Remove, ContainsKey, TryGetValue

  • Add(key, value) — adiciona um novo par
  • Remove(key) — remove pela chave
  • ContainsKey(key) — verifica se a chave existe
  • TryGetValue(key, out value) — pega o valor de forma segura (sem exceção se não tiver a chave)

4. Usando IDictionary<TKey, TValue> na prática

Métodos genéricos

Digamos que tu tá escrevendo uma função que tem que funcionar com qualquer dicionário, mas não quer saber qual classe tá por trás: pode ser um Dictionary normal, um SortedDictionary, ou até alguém inventou um “dicionário cripto doidão”.

Tu declara o parâmetro como IDictionary<TKey, TValue>:


static void PrintDictionary<TKey, TValue>(IDictionary<TKey, TValue> someDictionary)
{
    foreach (var pair in someDictionary)
    {
        Console.WriteLine($"{pair.Key}: {pair.Value}");
    }
}

Agora teu método aceita qualquer dicionário! Por baixo dos panos pode ser qualquer coisa — até um dicionário que criptografa os valores, se tu curtir esse tipo de emoção.

Usando IDictionary pra passar parâmetros

Imagina que tu tá fazendo um app pra registrar gatinhos, e quer que teu método funcione com qualquer dicionário de configurações, não só uma classe específica. Olha só como fica:


void SetCatParameters(IDictionary<string, string> parameters)
{
    if (parameters.ContainsKey("color"))
    {
        Console.WriteLine($"Pinte o gatinho de cor: {parameters["color"]}");
    }
}

Uma assinatura — várias implementações

Explicando com uma tabela marota:

Classe da coleção Implementa IDictionary<TKey,TValue> Características
Dictionary<TKey, TValue>
✅ Sim Busca rápida, chaves em ordem aleatória
SortedDictionary<TKey,TValue>
✅ Sim Chaves são ordenadas automaticamente
SortedList<TKey, TValue>
✅ Sim Chaves ordenadas, mais econômico em memória
(Sua própria classe que implementa a interface) ✅ Sim Qualquer lógica tua, mas tem que seguir o contrato

5. Relação com outras interfaces de coleção

Pra quem curte detalhes: a interface IDictionary<TKey, TValue> herda de ICollection<KeyValuePair<TKey, TValue>> e IEnumerable<KeyValuePair<TKey, TValue>>. Isso significa que qualquer dicionário pode:

  • Ser percorrido com foreach pelos pares chave-valor,
  • Adicionar e remover pares usando métodos da coleção,
  • Pegar a quantidade de elementos.

foreach (var entry in myDictionary)
{
    Console.WriteLine($"{entry.Key} => {entry.Value}");
}

6. Particularidades e erros comuns

Trabalhando com o indexador

Erro clássico de iniciante: tentar pegar um elemento por uma chave que não existe vai lançar KeyNotFoundException.


var value = myDictionary["NemaTakogoKlyucha"]; // Boom!

Por isso é sempre melhor usar TryGetValue:


if (myDictionary.TryGetValue("Murzik", out var cat))
{
    Console.WriteLine($"Achou o gatinho: {cat}");
}
else
{
    Console.WriteLine($"Gatinho não encontrado!");
}

Adicionar uma chave que já existe

Se tu chamar Add pra uma chave que já existe, vai tomar ArgumentException. Se quiser “adicionar ou atualizar”, usa o indexador:


// Adiciona se não tem, atualiza se já tem
myDictionary["Murka"] = new Cat("Murka", 5);

Percorrer e modificar

Não tenta modificar o dicionário (tipo, remover elementos) direto num foreach: vai dar exceção. Se precisar remover algo, primeiro monta uma lista de chaves pra remover, depois remove num loop separado:


// Jeito seguro de remover elementos
var keysToRemove = new List<string>();
foreach (var pair in myDictionary)
{
    if (pair.Value.Age > 10) // Condição pra remover
    {
        keysToRemove.Add(pair.Key);
    }
}

foreach (var key in keysToRemove)
{
    myDictionary.Remove(key);
}
1
Pesquisa/teste
Contrato de coleção, nível 28, lição 4
Indisponível
Contrato de coleção
Interfaces principais de coleções
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION