C# - Apresentando Boxing e Unboxing
Hoje vamos recordar os conceitos de boxing e unboxing na linguagem C#.

Podemos traduzir boxing como empacotar e unboxing como desempacotar mas creio que o melhor mesmo é nos referirmos aos termos originais boxing e unboxing pois será assim que serão referenciados na literatura e em artigos.

A linguagem C# possui dois tipos de dados :

  1. Tipos de valor
  2. Tipos de referência

O tipo de valor armazena o próprio valor, enquanto o tipo de referência armazena o endereço do valor em que está armazenado. Alguns tipos de dados predefinidos, como int, float, double, decimal, bool, char, etc. são tipos de valor e object, string e array são tipos de referência.

Ao trabalhar com esses tipos de dados, você geralmente precisa converter tipos de valor em tipos de referência ou vice-versa. Como ambos têm características diferentes e a plataforma .NET os armazena de maneira diferente na memória, é necessário trabalhar internamente para convertê-los de um tipo para outro.

Esses processos de conversão são chamados de boxing e unboxing.

O que é boxing ?

Boxing é o processo de converter um tipo de valor para o tipo de objeto ou qualquer tipo de interface implementado por esse tipo de valor, ou seja, converter um tipo de valor em um tipo de referência. Esta operação é implícita.

No processo da operação boxing temos que:

  • É o processo de converter um Tipo de Valor (char, int, long, etc) para um Tipo de Referencia (object, string, etc.)
  • É um processo de conversão implicita no qual o tipo object (super type) é usado;
  • O tipo de valor é sempre armazenado no Stack e o tipo de referência é armazenado na Heap;
  • Exemplo:

    
          int numero = 23 ;
        object obj = numero;    //Boxing 

    Descrição :

    • Declaramos um variável numero que um tipo de valor(int) atribuindo a ela o valor 23;
    • Criamos um tipo Object que é um tipo de referência e aplicamos uma operação implicita que resulta na cópia e armazenamento do tipo de valor no tipo de referência obj;

    Outro exemplo:

    
             ArrayList lista = new ArrayList();
          lista.Add(10);                  //Boxing 
          lista.Add("Macoratti");

    Criamos um ArrayList , que é um tipo de referência, chamado lista e incluímos um valor inteiro (10) na lista. Aqui estamos realizando o boxing que inclui o tipo de valor (10) em um tipo de referência (o array lista).

    Nota: Como as operações de boxing e unboxing causam uma perda de desempenho prefira usar as coleções genéricas ao invés de usar ArrayList.

    O que é Unboxing ?

    O Unboxing é o inverso do boxing.

    É o processo de converter um tipo de referência em tipo de valor. O unboxing extrai o  valor do tipo de referência e o atribui a um tipo de valor. Esta operação é explicita.

    Uma operação de conversão unboxing consiste em:

    • Verificar a instância do objeto para garantir que ele é um valor da conversão boxing de um determinado tipo de valor;
    • Copiar o valor da instância para a variável de tipo de valor;

    Exemplo:

    
           int i = 123;       //tipo de valor
          object o = i;     // boxing
          int j = (int)o;     // unboxing
    

    Aqui estamos copiando o tipo de referência o para o tipo de valor j.

    A figura abaixo demonstra as operações :

    Para que uma conversão de unboxing em um determinado tipo de valor seja bem-sucedida em tempo de execução, o valor do argumento de origem deve ser uma referência a um objeto que foi criado anteriormente via operação boxing do tipo de valor.

    Se o argumento de origem for uma referência a um objeto incompatível, uma InvalidCastException será lançada, e se o valor for null obteremos um NullReferenceException.

    Exemplo:

    class Program
        {
            static void Main(string[] args)
            {
                int i = 123;
                object o = i;  //boxing
                try
                {
                    int j = (short)o;         // tentativa de fazer unboxing
                    System.Console.WriteLine("Operação de Unboxing OK.");
                }
                catch (System.InvalidCastException e)
                {
                    System.Console.WriteLine($"{e.Message} Error: Operação de unboxing inválida.");
                }
            }
        }

    Este programa produz o seguinte resultado :

    Se você alterar a instrução:

    int j = (short) o;   para:     int j = (int) o;
    a conversão será executada e você receberá a saída:  Operação de Unboxing OK

    E estamos conversados...

    "Porque o reino de Deus não é comida nem bebida, mas justiça, e paz, e alegria no Espírito Santo."
    Romanos 14:17

    Referências:


    José Carlos Macoratti