Fa unboxing solo restituire un puntatore al valore all'interno dell'oggetto in scatola sul mucchio?

StackOverflow https://stackoverflow.com/questions/2978647

  •  24-10-2019
  •  | 
  •  

Domanda

I questo articolo MSDN Magazine, l'autore afferma (sottolineatura mia ):

Si noti che la boxe crea sempre un nuovo oggetto e copia il valore unboxed del bit per l'oggetto. D'altra parte, unboxing semplicemente restituisce un puntatore a i dati all'interno di un oggetto boxed: no copia di memoria si verifica. Tuttavia, è comunemente il caso che il codice verrà causare i dati puntato dal di riferimento unboxing da copiare in ogni caso.

Sono confuso dalla frase che ho in grassetto e la frase che lo segue. Da tutto il resto che ho letto, tra cui questa pagina MSDN , I' ve mai sentito prima che unboxing solo restituisce un puntatore al valore sul mucchio. Ho avuto l'impressione che unboxing si tradurrebbe in voi avere una variabile che contiene una copia del valore sullo stack, proprio come si è iniziato con. Dopo tutto, se la mia variabile contiene "un puntatore al valore sul mucchio", quindi non ho avuto un tipo di valore, ho un puntatore.

qualcuno può spiegare cosa significa questo? Era l'autore di crack? (C'è almeno un altro madornale errore in questo articolo). E se questo è vero, quali sono i casi in cui "il codice farà sì che i dati di cui punta il riferimento unboxing da copiare in ogni caso"?

Ho appena notato che l'articolo è quasi 10 anni, quindi forse questo è qualcosa che ha cambiato molto presto nella vita di .Net.

È stato utile?

Soluzione

L'articolo è accurata. E 'però parla di ciò che davvero va avanti, non ciò che gli sguardi IL genere il compilatore genera. Dopo tutto, un programma di .NET non esegue IL, viene eseguito il codice macchina che è generato dalla IL dal compilatore JIT.

E l'Unbox opcode genera infatti codice che produce un puntatore ai bit sul mucchio che rappresenta il valore del tipo valore. Il JIT genera una chiamata a una piccola funzione di supporto nel CLR denominato "JIT_Unbox". CLR \ src \ vm \ jithelpers.cpp se hai il codice sorgente SSCLI20. L'oggetto :: GetData () restituisce la funzione del puntatore.

Da lì, il valore più comunemente prima viene copiato in un registro della CPU. Che poi potrebbe vengono memorizzati da qualche parte. Non deve essere stack, potrebbe essere un membro di un oggetto di tipo di riferimento (il mucchio gc). O una variabile statica (il mucchio loader). Oppure potrebbe essere spinto sulla pila (chiamata al metodo). O registrati la CPU potrebbe essere utilizzato come-è quando il valore viene utilizzato in un'espressione.

Durante il debug, pulsante destro del mouse nella finestra dell'editor e scegliere "Vai a Smontaggio" per vedere il codice macchina.

Altri suggerimenti

L'autore dell'articolo originale deve essere stato riferiva a ciò che sta accadendo in basso a livello di IL. Esistono due codici operativi unboxing: unbox e unbox.any

.

Secondo MSDN, riguardo unbox.any :

Quando applicato alla forma scatolata di un tipo di valore, l'istruzione unbox.any estratti il ??valore contenuto all'interno obj (di tipo O), ed è quindi equivalente a Unbox seguito da ldobj.

riguardo unbox :

[...] Unbox non è tenuto a copia il tipo di valore dall'oggetto. Tipicamente calcola semplicemente la indirizzo del tipo valore che è già presente all'interno della scatola oggetto.

Quindi, l'autore sapeva quello che stava parlando.

Questo piccolo fatto che riguarda unbox permette di fare certe ottimizzazioni nifty quando si lavora direttamente con IL. Ad esempio, se si dispone di un int scatolato che è necessario passare ad una funzione che accetta un int ref, si può semplicemente emettere un opcode unbox, e il riferimento all'int sarà pronto nella pila per la funzione di operare sia. In questo caso la funzione cambierà il contenuto effettivo dell'oggetto boxe, cosa che è del tutto impossibile a livello di C #. Esso consente di risparmiare dalla necessità di allocare spazio per una variabile locale temporanea, Unbox int in là, passare un ref per l'int alla funzione, e quindi creare un nuovo oggetto di boxe per ri-box int, scartando la vecchia scatola.

Naturalmente, quando si lavora a livello di C #, non si può fare tali ottimizzazioni, così quello che di solito accadere è che il codice generato dal compilatore sarà quasi sempre la copia la variabile dall'oggetto in scatola prima di effettuare ogni ulteriore uso di esso.

La boxe è l'atto di fusione un'istanza valore di tipo a un'istanza di riferimento di tipo (un object o un'interfaccia), e tipi di riferimento sono allocati sul mucchio.

Secondo 'C # 4.0 in a Nutshell':. "... unboxing copie il contenuto della schiena oggetto in un'istanza valore-tipo" e che implica sullo stack

In questo articolo si fa riferimento, l'autore afferma:

public static void Main() {

   Int32 v = 5;    // Create an unboxed value type variable
   Object o = v;   // o refers to a boxed version of v
   v = 123;        // Changes the unboxed value to 123

   Console.WriteLine(v + ", " + (Int32) o);    // Displays "123, 5"
}

Da questo codice, si può indovinare quanti si verificano le operazioni di boxe? Potresti essere sorpreso di scoprire che la risposta è tre! Analizziamo il codice con attenzione per capire veramente che cosa è in corso. In primo luogo, un tipo di valore unboxed Int32 (v) viene creato e inizializzato a 5. Quindi viene creato un tipo di riferimento oggetto (o) e vuole indicare v. Ma i tipi di riferimento devono sempre puntare agli oggetti nel mucchio, in modo da C # generato il codice IL propria casella v e conservato l'indirizzo della scatola versione di v in o. Ora 123 è unboxed ei dati di riferimento viene copiato in il tipo unboxed valore v; questo non ha effetto sulla versione in scatola di v, in modo la versione in scatola mantiene il suo valore 5. Si noti che questo esempio mostra come O è unboxed (che restituisce un puntatore a i dati in O), e quindi i dati in o è memoria copiata valore unboxed . Tipo di v

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top