Boxing e unboxing (Guida per programmatori C#)Boxing and Unboxing (C# Programming Guide)

Il boxing è il processo di conversione di un tipo di valore nel tipo object o in qualsiasi tipo di interfaccia implementato dal tipo valore.Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. Quando il CLR esegue il boxing di un tipo di valore, incapsula il valore in un'istanza System.Object e lo archivia nell'heap gestito.When the CLR boxes a value type, it wraps the value inside a System.Object instance and stores it on the managed heap. Mediante la conversione unboxing, invece, il tipo valore viene estratto dall'oggetto.Unboxing extracts the value type from the object. La conversione boxing è implicita; quella unboxing è esplicita.Boxing is implicit; unboxing is explicit. Il concetto di conversione boxing e unboxing è alla base della visione unificata del sistema dei tipi in C#, in base alla quale un valore di qualsiasi tipo può essere considerato come un oggetto.The concept of boxing and unboxing underlies the C# unified view of the type system in which a value of any type can be treated as an object.

Nell'esempio seguente viene eseguita la conversione boxing della variabile intera i e la sua assegnazione all'oggetto o.In the following example, the integer variable i is boxed and assigned to object o.

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

È quindi possibile eseguire l'unboxing dell'oggetto o e la sua assegnazione alla variabile intera i:The object o can then be unboxed and assigned to integer variable i:

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

Nell'esempio seguente viene illustrato l'utilizzo della conversione boxing in C#.The following examples illustrate how boxing is used in 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

PrestazioniPerformance

Rispetto alle semplici assegnazioni, le conversioni boxing e unboxing sono processi onerosi dal punto di vista del calcolo.In relation to simple assignments, boxing and unboxing are computationally expensive processes. La conversione boxing di un tipo valore comporta infatti l'allocazione e la costruzione di un nuovo oggetto.When a value type is boxed, a new object must be allocated and constructed. A un livello inferiore, anche il cast richiesto per la conversione unboxing è oneroso dal punto di vista del calcolo.To a lesser degree, the cast required for unboxing is also expensive computationally. Per altre informazioni, vedere Prestazioni.For more information, see Performance.

BoxingBoxing

La conversione boxing viene utilizzata per archiviare tipi valore nell'heap sottoposto a Garbage Collection.Boxing is used to store value types in the garbage-collected heap. Il boxing è una conversione implicita di un tipo di valore al tipo object o a qualsiasi tipo di interfaccia implementato da questo tipo di valore.Boxing is an implicit conversion of a value type to the type object or to any interface type implemented by this value type. La conversione boxing di un tipo valore prevede l'allocazione di un'istanza dell'oggetto nell'heap e la copia del valore nel nuovo oggetto.Boxing a value type allocates an object instance on the heap and copies the value into the new object.

Si consideri la seguente dichiarazione di una variabile di tipo valore:Consider the following declaration of a value-type variable:

int i = 123;

L'istruzione seguente applica implicitamente l'operazione di conversione boxing alla variabile i:The following statement implicitly applies the boxing operation on the variable i:

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

Il risultato di questa istruzione è la creazione, sullo stack, di un riferimento all'oggetto o che fa riferimento a un valore di tipo int nell'heap.The result of this statement is creating an object reference o, on the stack, that references a value of the type int, on the heap. Questo valore è una copia di quello di tipo valore assegnato alla variabile i.This value is a copy of the value-type value assigned to the variable i. La differenza tra le due variabili i e o è illustrata nella figura seguente della conversione boxing:The difference between the two variables, i and o, is illustrated in the following image of boxing conversion:

Figura che mostra la differenza tra le variabili i e o.

È inoltre possibile, anche se non obbligatorio, eseguire la conversione boxing in modo esplicito, come nell'esempio seguente:It is also possible to perform the boxing explicitly as in the following example, but explicit boxing is never required:

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

DESCRIZIONEDescription

In questo esempio viene eseguita la conversione boxing della variabile intera i in un oggetto o.This example converts an integer variable i to an object o by using boxing. Il valore archiviato nella variabile i viene quindi modificato da 123 a 456.Then, the value stored in the variable i is changed from 123 to 456. Nell'esempio il tipo valore originale e l'oggetto sottoposto a conversione boxing utilizzano posizioni di memoria separate, pertanto possono archiviare valori diversi.The example shows that the original value type and the boxed object use separate memory locations, and therefore can store different values.

EsempioExample

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 doesn't affect 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
*/

Conversione unboxingUnboxing

L'unboxing è una conversione esplicita dal tipo object a un tipo di valore o da un tipo di interfaccia a un tipo di valore che implementa l'interfaccia.Unboxing is an explicit conversion from the type object to a value type or from an interface type to a value type that implements the interface. Un'operazione unboxing prevede le operazioni seguenti:An unboxing operation consists of:

  • Controllo dell'istanza di oggetto per verificare che si tratti di un valore sottoposto a conversione boxing del tipo valore specificato.Checking the object instance to make sure that it is a boxed value of the given value type.

  • Copia del valore dall'istanza alla variabile di tipo valore.Copying the value from the instance into the value-type variable.

Le istruzioni seguenti illustrano operazioni di conversione boxing e unboxing:The following statements demonstrate both boxing and unboxing operations:

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

La figura seguente mostra il risultato delle istruzioni precedenti:The following figure demonstrates the result of the previous statements:

Figura che illustra una conversione unboxing.

Per eseguire correttamente la conversione unboxing di tipi valore in fase di esecuzione, è necessario che l'elemento sottoposto a conversione unboxing faccia riferimento a un oggetto creato in precedenza tramite la conversione boxing di un'istanza di tale tipo valore.For the unboxing of value types to succeed at run time, the item being unboxed must be a reference to an object that was previously created by boxing an instance of that value type. Il tentativo di eseguire la conversione unboxing di un valore null genera NullReferenceException.Attempting to unbox null causes a NullReferenceException. Il tentativo di eseguire la conversione unboxing di un riferimento a un tipo valore incompatibile genera InvalidCastException.Attempting to unbox a reference to an incompatible value type causes an InvalidCastException.

EsempioExample

Nell'esempio riportato di seguito viene illustrato un caso di unboxing non valido, nonché l'elemento InvalidCastException risultante.The following example demonstrates a case of invalid unboxing and the resulting InvalidCastException. Se si utilizza try e catch, quando si verifica l'errore viene visualizzato un messaggio di errore.Using try and catch, an error message is displayed when the error occurs.

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);
        }
    }
}

Questo programma restituisce:This program outputs:

Specified cast is not valid. Error: Incorrect unboxing.

Se si modifica l'istruzione:If you change the statement:

int j = (short) o;  

in:to:

int j = (int) o;  

la conversione verrà eseguita e si otterrà l'output:the conversion will be performed, and you will get the output:

Unboxing OK.

Specifiche del linguaggio C#C# Language Specification

Per altre informazioni, vedere la specifica del linguaggio C#.For more information, see the C# Language Specification. La specifica del linguaggio costituisce il riferimento ufficiale principale per la sintassi e l'uso di C#.The language specification is the definitive source for C# syntax and usage.

Per ulteriori informazioni:For more information:

Vedere ancheSee also