Conhecendo C# - Tipos - Parte 6
Conhecendo C# - Tipos - Parte 6
Boxing e Unboxing
Diferentemente de algumas linguagens orientada à objetos, o C# não exige um wrapper(empacotador) para manipular objetos e tipos, uma técnica muito mais poderosa é utilizada neste caso boxing e unboxing.
Boxing é a conversão de um tipo valor para um tipo referência e unboxing é o processo contrário desta conversão, ou seja extrai-se o conteúdo do tipo valor de um tipo referência herdado de System.ValueType. Somente conversões explícitas são suportadas para unboxing.
//Boxing //Unboxing |
Os tipos de dados herdados por System.ValueTypes são alocados em stack, por serem implementados como estrutura(struct), vide documentação de System.Int32 no .NET Framework SDK, por exemplo. Quando uma variável do tipo valor é utilizada, apenas seu contéudo é alocado em memória, no entanto se essa variável sofrer uma operação de boxing, seu valor será copiado para a heap e será acrescentado o overhead(excesso) do objeto System.ValueTypes(objeto herdado de System.Object, raíz de todos objetos do .NET Framework). A figura 4 exibe o estado do exemplo anterior que manipula um inteiro nas duas formas: boxing e unboxing.
Figura 4: Representação em memória de uma variável int nas formas boxing e unboxing
O que deve ficar claro no processo de conversão, é que o boxing pode ser tratado automáticamente, ou seja implícito, por exemplo para um inteiro(int) tornar-se um objeto(object) poderemos encontrar object o = 12345, neste caso o valor 12345 é tratado como inteiro(int). No entanto na forma unboxing, o tratamento explícito é requerido int x = (int)o, assumindo que o representa um object. Se a partir da forma boxing de um valor, através de conversão explícita, deseja-se obter a forma unboxing do mesmo, o cast no processo de unboxing deverá ser coerente com o tipo específicado, caso contrário um excessão InvalidCastException será disparada, isto também é válido para casts inconsistenes. O código abaixo demonstra isso:
long l = 12345; //Unboxing inconsistente |
Segue a correção para o exemplo acima:
long l = 12345; //Unboxing consistente |
Uma outra forma de utilizar as conversões é atráves da operação através de seus membros, ou seja, a partir de um conteúdo ou de uma variável é possível especificar a função ou método de conversão desejado. Se uma variável ou valor é de um tipo determinado, por exemplo, de um tipo int é correto utilizar i.ToInt64() ou 12345.ToInt64() para obter-se um valor do tipo long. O código anterior pode ser reescrito para:
object o = 12345.ToInt64(); //Valor tratado na forma boxing |
De acordo com documentação do .NET Framework, se utilizarmos o método WriteLine da classe Console com uma string formatadora e vários tipos de dados, esses tipos serão tratados como um vetor(array) de objetos, conforme figura 5. Então quantos boxings serão executados na linha abaixo?
long l = 1000; |
Figura 5: Uma das possibilidades do método WriteLine da classe Console
Seriam necessários 6 boxings para última linha, um para cada variável a ser tratada como objeto. O processo de boxing consome memória e tempo de execução da CPU, portanto o código acima é eficientemente reescrito para:
long l = 1000; |
Neste caso o número de boxings é reduzido 2. Este tipo de cuidado sempre deverá ser tomado para a obtenção da melhor performance do código, resultando menos tempo de processamento e recursos consumidos.
Próximo artigo: .