Estruturas de Dados em .NET: Dicionário

Junto com algoritmos, estruturas de dados são um tema fundamental para a formação de qualquer desenvolvedor, independente da linguagem.

Nessa série, vou discutir algumas estruturas de dados, e mostrar as implementações disponibilizadas em .NET e seu uso de maneira prática. Neste artigo, especificamente, eu falo sobre a estrutura de dados Dicionário. Bora lá?

Artigo já publicado sobre Estruturas de Dados:


O que é Dicionário?

Acredito que utilizar um exemplo do mundo real auxilia bastante no entendimento de novos conceitos. Dito isso, o próprio dicionário, que você já deve ter utilizado muitas vezes nessa vida, dá uma dica de como essa estrutura de dados funciona.

Estes são os passos de quando você deseja encontrar um significado no dicionário:

  • Você abre o dicionário
  • Começa buscar pela palavra nele
  • Ao achar, você obtém o significado dele

Cada registro no dicionário contém a chave (por exemplo, “processador”) e um valor (significado de “processador”). Através da chave que você encontra o valor no dicionário, e neste caso ambos são do tipo texto.

Com este exemplo dado, apresento aqui o significado mais formal de um Dicionário:

O Dicionário é uma estrutura de dados que armazena pares de chave-valor. O valor armazenado não está restrito a um tipo único, permitindo armazenar valores mais complexos como outros objetos ou coleções.

Um objeto JSON, por exemplo, tem estrutura similar a um dicionário.


Dicionário em .NET: Dictionary

O .NET oferece a estrutura de dados Dicionário na forma do Dictionary<T, K>, onde T é o tipo da chave, e K o tipo do valor armazenado.

Existem algumas maneiras de iniciar um dicionário, o que mostro logo abaixo.

var mappings = new Dictionary<string, string>();

            var mappingsPopulated = new Dictionary<string, string> {
                { "Title", "name"},
                { "Length", "len" },
                { "Address", "addr" }
            };

            var mappingsPopulatedAlternative = new Dictionary<string, string>
            {
                ["Title"] = "name",
                ["Length"] = "len",
                ["Address"] = "addr"
            };

Operações

As principais operações de um dicionário são:

  • Add(Key, Value): adiciona a chave e o valor especificados;
  • ContainsKey(Key): verifica se o dicionário contém a chave especificada;
  • Remove(Key): remove o registro que contenha a chave especificada;
  • TryGetValue(Key, out Value): tenta obter o valor da chave especificada, retornando false caso a chave não exista no dicionário.

Dá para acessar o valor através de uma chave e indexador ([]);

Abaixo eu coloco código utilizando todas essas operações, além do acesso de valor via índice.

            var dicionarioProgramador = new Dictionary<string, string>
            {
                { "Gambiarra", "Solução improvisada para resolver um problema ou para remediar uma situação de emergência." }
            };

            dicionarioProgramador.Add("Daily", "Reunião para bater ponto e dizer que está trabalhando, na maioria das equipes.");
            dicionarioProgramador.Add("Refatoração", "Não temos tempo para colocar o significado dessa palavra, a entrega é para amanhã (todos os dias é assim).");

            var significadoGambiarra = dicionarioProgramador["Gambiarra"];

            dicionarioProgramador.Remove("Refatoração");

            if (!dicionarioProgramador.ContainsKey("Refatoração"))
            {
                Console.WriteLine("Dicionário não contém significado de Refatoração.");
            }

            if (dicionarioProgramador.TryGetValue("Daily", out var significadoDaily)) {
                Console.WriteLine(significadoDaily);
            }

Exemplo

Abaixo eu mostro um exemplo de seu uso. A ideia é realizar um mapeamento de um objeto para um JSON dinâmico, baseado em um dicionário de mapeamento de propriedades (com chave e valor de tipo string). É um cenário realista e comum em aplicações que dependem de um mapeamento mais dinâmico. Os dados do dicionário poderiam, por exemplo, estarem armazenados em uma tabela de banco de dados, e serem mapeados para um dicionário em memória para então serem utilizados.

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text.Json;

namespace ArtigoDictionary
{
    class Program
    {
        static void Main(string[] args)
        {
            // Dicionário que contém o mapeamento entre as propriedades de minha classe para um JSON de integração com outro sistema
            var mappingsPopulated = new Dictionary<string, string> {
                { "Title", "name"},
                { "Length", "len" },
                { "Address", "addr" }
            };

            // beachProperty é o objeto que quero mapear para um JSON de integração
            var beachProperty = new Property("Beach house", 50.5m, "Awesome Beach, 123, BR");

            // Obtenho o Type para posteriormente utilizar Reflection e atribuir o valor no meu dicionário
            var propertyType = beachProperty.GetType();

            // Dicionário que vai conter os pares chave-valor do JSON que quero mapear a partir do meu objeto beachProperty
            var integrationObject = new Dictionary<string, object>();

            // Percorro o dicionário, com cada item sendo do tipo KeyValuePair<string, string>
            foreach (var keyValuePair in mappingsPopulated)
            {
                // Atribuo ao dicionário com chave da propriedade mapeada ao JSON de integração, e utilizo Reflection para obter a propriedade e valor de maneira dinâmica
                integrationObject[keyValuePair.Value] = propertyType.GetProperty(keyValuePair.Key).GetValue(beachProperty);
            }

            // Converto o dicionário para um JSON
            var jsonIntegrationObject = JsonSerializer.Serialize(integrationObject);

            Console.WriteLine(jsonIntegrationObject);

            Console.Read();
        }
    }

    public class Property
    {
        public Property(string title, decimal length, string address)
        {
            Title = title;
            Length = length;
            Address = address;
        }

        public string Title { get; set; }
        public decimal Length { get; set; }
        public string Address { get; set; }
    }
}

Conclusão

Foi abordado neste artigo a estrutura de dados Dicionário, sendo apresentados os seus principais conceitos e um exemplo prático com .NET e C#.

Reforço a importância de entender bem as estruturas de dados disponíveis, para que possa sempre escolher as mais adequadas para resolver o problema em mãos.