2009-04-18 16 views
27

Un'altra domanda di intervista in C# recente è stata se sapessi cosa sono Boxing e Unboxing. Ho spiegato che i tipi di valore sono su Stack e tipi di riferimento su Heap. Quando un valore viene lanciato su un tipo di riferimento, lo chiamiamo boxing e viceversa.Boxing vs Unboxing

Poi mi ha chiesto di calcolare questo:

int i = 20; 
object j = i; 
j = 50; 

Che cosa è i?

ho messo in su e disse: 50, in cui la sua realtà 20. Ora penso capire il motivo per cui, tuttavia quando stavo giocando con diverse combinazioni sono rimasto sorpreso di vedere questo:

Object a = 1; // Boxing 
Object b = a; // referencing the pointer on stack to both objects on heap 
a = 2; // Boxing 

mi aspettavo di vedi anche b == 2, ma non lo è, perché? È perché il secondo boxing distrugge e sostituisce l'intero oggetto a sull'heap?

Perché se faccio questo, va bene:

public class TT 
{ 
    public int x; 
} 

TT t = new TT(); 
t.x = 1; 
TT t2 = new TT(); 
t2.x = 2; 
t = t2; 
t.x = 3; 

Che cosa è t2.x? Dovrebbe essere 3, e lo è. Ma questo non è affatto un esempio di boxing/unboxing, è corretto? Quindi, come lo riassumeresti?

I valori possono essere sempre gli stessi in una conversione di boxe/unboxing come sopra?

+1

vedi anche http://stackoverflow.com/questions/13055/what-is-boxing-and-unboxing-and-what-are-the -Trade-off per una lettura generale – nawfal

risposta

5
  1. Hai ragione il secondo incarico sostituisce il primo. Non cambia il valore in scatola.

  2. L'esempio non utilizza il pugilato. Il valore (int) è memorizzato come int e non in scatola.

  3. No, la boxe mantiene ancora la garanzia di immutabilità.

+0

Ciao, grazie per la risposta. potresti per favore approfondire un po 'di più su "il pugilato conserva ancora la garanzia di immutabilità"? Grazie kave – Houman

+1

La maggior parte dei tipi di valore è immutabile, ad esempio: Un int può avere solo un valore. Se cambi il valore in sostanza stai creando un nuovo int. .NET mantiene questa immutabilità per gli oggetti in scatola: se gli assegni un nuovo valore, stai creando una nuova int in scatola. Lo stesso vale per le strutture scatolate. – grover

+0

Ha perfettamente senso. Grazie – Houman

2

mi aspettavo di vedere b == 2, nonché, ma non lo è, perché? è perché il secondo boxing distrugge e sostituisce l'intero (a) -oggetto sull'heap?

No, non esattamente. Lascia l'oggetto così com'è nell'heap (come la variabile b fa anche riferimento a esso) e crea un nuovo oggetto per il nuovo valore, cui farà riferimento la variabile a.

Hai ragione che il tuo secondo esempio non usa il pugilato. Non è possibile accedere a un valore inserito in un altro modo diverso dall'unboxing, quindi non c'è modo di modificare un valore box.

Neanche una struttura mutevole come Point può essere modificata quando inserito. Per accedere alle proprietà della struttura devi eliminarlo, quindi non puoi modificare la struttura in scatola.

1

b è ancora 1 perché b è un riferimento che punta ancora all'oggetto sull'heap con un valore di 1. a è 2 perché lo hai assegnato a un nuovo oggetto sull'heap con un valore di 2.

t2.x è 3 perché t e t2 sono due diversi riferimenti allo stesso oggetto sull'heap.

0

Penso che la risposta alla tua domanda con unboxing sia la seguente: Il risultato di una conversione di unboxing è una variabile temporanea (ulteriori dettagli: link).

penso che si stava tentando di fare qc come:

object a = new Point(10,10); 
object b = new Point(20,20); 
a = b; 

((Point) b).X = 30; //after this operation also a.X should be 30 

Il codice di cui sopra non compilerà - dettagli nel link qui sopra, e credo che questa è la risposta alla tua domanda:

Mi aspettavo di vedere anche b == 2, ma non lo è, perché? è perché il secondo boxing distrugge e sostituisce l'intero (a) -oggetto sull'heap?

+0

Vale la pena notare che in C++/CLI, non vi è alcuna difficoltà a modificare gli oggetti heap in box direttamente all'interno di codice affidabile e verificabile. – supercat

8

molto breve: mezzi di inscatolamento creare una nuova istanza di un tipo di riferimento. Se lo sai, capisci che un'istanza non cambia creando un'altra.

Quello che stai facendo con a = 2 non sta cambiando il valore nella 'casella', stai creando una nuova istanza di un tipo di riferimento. Quindi perché dovrebbe cambiare qualcos'altro?

+1

bella spiegazione, ora cosa succede quando si cancella? la nuova istanza di riferimento viene distrutta? – SoftwareGeek

+1

I tipi di riferimento vengono sempre distrutti dalla procedura di Garbage Collection. Quindi sarà distrutto quando non sarà più referenziato. –

+0

breve n dolce risposta, davvero bella – FosterZ

2

Ecco un altro interessante variante che supporta i commenti di Stefan:

 int i = 2; 
     object a = i; // Boxing 
     object b = a; // Referencing same address on heap as 'a', b == a 

     b = i; // New boxing on heap with reference new address, b != a 
Problemi correlati