Compartilhar via


Conversões boxing e unboxing (Guia de Programação em C#)

O encapsulamento é um processo de conversão de um tipo de valor para o tipo object ou para qualquer tipo de interface implementado por este tipo de valor. Quando o CLR fecha um tipo de valor, ele envolve o valor dentro de um System.Object e o armazena no heap gerenciado. O unboxing extrai o tipo do valor do objeto. O encapsulamento é implícito; o desencapsulamento é explícito. O conceito de boxing e unboxing se baseia na exibição unificada do C# do sistema do tipo no qual um valor de qualquer tipo pode ser tratado como objeto.

No exemplo a seguir, a variável inteira i é encapsulada e atribuída ao objeto o.

int i = 123;
// The following line boxes i. 
object o = i;  

O objeto o pode então ser unboxed e atribuído à variável inteira i:

o = 123;
i = (int)o;  // unboxing

Os exemplos a seguir ilustram como boxing é usado no C#.

// String.Concat example. 
// String.Concat has many versions. Rest the mouse pointer on  
// Concat in the following statement to verify that the version 
// that is used here takes three object arguments. Both 42 and 
// true must be boxed.
Console.WriteLine(String.Concat("Answer", 42, true));


// List example. 
// Create a list of objects to hold a heterogeneous collection  
// of elements.
List<object> mixedList = new List<object>();

// Add a string element to the list. 
mixedList.Add("First Group:");

// Add some integers to the list.  
for (int j = 1; j < 5; j++)
{
    // Rest the mouse pointer over j to verify that you are adding 
    // an int to a list of objects. Each element j is boxed when  
    // you add j to mixedList.
    mixedList.Add(j);
}

// Add another string and more integers.
mixedList.Add("Second Group:");
for (int j = 5; j < 10; j++)
{
    mixedList.Add(j);
}

// Display the elements in the list. Declare the loop variable by  
// using var, so that the compiler assigns its type. 
foreach (var item in mixedList)
{
    // Rest the mouse pointer over item to verify that the elements 
    // of mixedList are objects.
    Console.WriteLine(item);
}

// The following loop sums the squares of the first group of boxed 
// integers in mixedList. The list elements are objects, and cannot 
// be multiplied or added to the sum until they are unboxed. The 
// unboxing must be done explicitly. 
var sum = 0;
for (var j = 1; j < 5; j++)
{
    // The following statement causes a compiler error: Operator  
    // '*' cannot be applied to operands of type 'object' and 
    // 'object'.  
    //sum += mixedList[j] * mixedList[j]); 

    // After the list elements are unboxed, the computation does  
    // not cause a compiler error.
    sum += (int)mixedList[j] * (int)mixedList[j];
}

// The sum displayed is 30, the sum of 1 + 4 + 9 + 16.
Console.WriteLine("Sum: " + sum);

// Output: 
// Answer42True 
// First Group: 
// 1 
// 2 
// 3 
// 4 
// Second Group: 
// 5 
// 6 
// 7 
// 8 
// 9 
// Sum: 30

Desempenho

Com relação às atribuições simples, boxing e unboxing são processos computacionalmente caros. Quando um tipo de valor é convertido, um novo objeto deve ser alocado e criado. Em menor grau, a conversão é exigida unboxing também cara computacionalmente. Para obter mais informações, consulte Desempenho.

Boxing

O encapsulamento é usado para armazenar tipos de valor na heap do lixo coletado. O encapsulamento é uma conversão implícita de um tipo de valor para o tipo object ou para qualquer tipo de interface implementado por este tipo de valor. Encapsular um tipo de valor atribui uma instância de objeto na heap e copia o valor para o novo objeto.

Considere a seguinte declaração de uma variável do tipo de valor:

int i = 123;

A instrução a seguir aplica implicitamente a operação de boxing na variável i:

// Boxing copies the value of i into object o. 
object o = i;  

O resultado dessa instrução é a criação de umo de referência do objeto na pilha que faz referência a um valor no tipo int, no heap. Esse valor é uma cópia do valor do tipo de valor atribuído a ivariável. A diferença entre duas variáveis, i e o, é ilustrada na figura a seguir.

Conversão de boxing

Gráfico de BoxingConversion

Também é possível executar o encapsulamento explicitamente como no exemplo a seguir, mas o encapsulamento explícito nunca é necessário:

int i = 123;
object o = (object)i;  // explicit boxing

Descrição

Este exemplo converte uma variável inteiro i a um objeto o usando o boxing. Em seguida, o valor armazenado na variável i é alterado de 123 a 456. O exemplo mostra esse tipo de valor original e o uso do objeto disponível usam locais de memória diferentes, portanto podem armazenar valores diferentes.

Exemplo

class TestBoxing
{
    static void Main()
    {
        int i = 123;

        // Boxing copies the value of i into object o. 
        object o = i;  

        // Change the value of i.
        i = 456;  

        // The change in i does not effect the value stored in o.
        System.Console.WriteLine("The value-type value = {0}", i);
        System.Console.WriteLine("The object-type value = {0}", o);
    }
}
/* Output:
    The value-type value = 456
    The object-type value = 123
*/

O exemplo a seguir demonstra um caso de unboxing inválido e InvalidCastException resultante. Usando try e catch, uma mensagem de erro é exibida quando o erro ocorre.

class TestUnboxing
{
    static void Main()
    {
        int i = 123;
        object o = i;  // implicit boxing 

        try
        {
            int j = (short)o;  // attempt to unbox

            System.Console.WriteLine("Unboxing OK.");
        }
        catch (System.InvalidCastException e)
        {
            System.Console.WriteLine("{0} Error: Incorrect unboxing.", e.Message);
        }
    }
}

Saída do programa:

Specified cast is not valid. Error: Incorrect unboxing.

Se você alterar a instrução:

int j = (short) o;

até:

int j = (int) o;

a conversão será executada, e você receberá a saída:

Unboxing OK.

Unboxing

O unboxing é uma conversão explícita do tipo object para um tipo de valor ou de um tipo da interface para um tipo de valor que implementa a interface. Uma operação unboxing consiste de:

  • Verificando a instância de objeto para certificar-se que é um valor convertido do tipo de valor dado.

  • Copiando o valor da instância na variável do tipo de valor.

AS instruções a seguir demonstram as operações de boxing e unboxing:

int i = 123;      // a value type 
object o = i;     // boxing 
int j = (int)o;   // unboxing

A figura a seguir mostra o resultado das instruções anteriores.

Conversão de unboxing

Gráfico de conversão unBoxing

Para unboxing de tipos de valores a serem sucedidos em tempo de execução, o item que está sendo unboxed deve ser uma referência a um objeto criado anteriormente por meio de boxing de uma instância desse tipo de valor. Tentar desencapsular null causar um NullReferenceException. Tentar desencapsular uma referência para um tipo de valor incompatível causará um InvalidCastException.

Especificação da Linguagem C#

Para obter mais informações, consulte a Especificação da linguagem C#. A especificação da linguagem é a fonte definitiva para a sintaxe e o uso de C#.

Seções relacionadas

Para obter mais informações:

Especificação da Linguagem C#

Para obter mais informações, consulte a Especificação da linguagem C#. A especificação da linguagem é a fonte definitiva para a sintaxe e o uso de C#.

Consulte também

Conceitos

Guia de Programação em C#