Area di riferimento
- Developing applications that use system types and collections
- Manage data in a .NET Framework application by using the .NET Framework 2.0 system types
- Boxing and UnBoxing
Boxing and Unboxing
Il boxing è un meccanismo che permette di convertire un value type in un reference type. L'operazione comporta l'allocazione di memoria heap, la copia dei campi del value type nel nuovo spazio di memoria e la restituzione dell'indirizzo del nuovo oggetto. Questo significa che dopo l'operazione di Boxing in realtà esistono due copie dei dati, una memorizzata nello stack e l'altra memorizzata nello heap. Ciò può portare a delle problematiche insidiose, per questo motivo è opportuno definire i value type come tipi immutabili. L'UnBoxing può essere considerata come l'operazione opposta al boxing che permette di convertire un boxing value type in un semplice value type.
Esempio di boxing and unboxing che utilizza la struttura Punto3D definita nel post "[70-536] User-Defined Value Types":
public struct Punto3D
{
public Punto3D(int x, int y, int z)
{
this.x = x;
this.y = y;
this.z = z;
}
public void Trasla(int dx, int dy, int dz)
{
x += dx;
y += dy;
z += dz;
}
public int x;
public int y;
public int z;
}
class Program
{
static public void visualizzaPunto3D(Punto3D p)
{
Console.WriteLine("({0}, {1}, {2})", p.x, p.y, p.z);
}
static void Main(string[] args)
{
Punto3D p1 = new Punto3D(10, 20, 30);
object obj = p1; // boxing
p1.Trasla(1, 2, 3);
Punto3D p2 = (Punto3D) obj; // unboxing
visualizzaPunto3D(p1);
visualizzaPunto3D(p2);
Console.ReadKey();
}
}
Il boxing è necessario quando si vogliono utilizzare i value types all'interno di collection le quali gestiscono riferimenti a object:
ArrayList lista = new ArrayList();
lista.Add(1); // boxing
lista.Add(2); // boxing
lista.Add(3); // boxing
foreach (int i in lista) // unboxing ad ogni iterazione
{
Console.WriteLine(i);
}
Con il .NET Framework 2.0 tuttavia questo overhead aggiuntivo può essere evitato utilizzando i generics:
List<int> lista = new List<int>();
lista.Add(1);
lista.Add(2);
lista.Add(3);
foreach (int i in lista)
{
Console.WriteLine(i);
}