Condividi tramite


Handle di rilevamento a un valore boxed

L'utilizzo di un handle di rilevamento per fare riferimento a un tipo di valore è stato modificato in Visual C++ 2010 rispetto alle estensioni gestite di C++.

Il boxing costituisce una caratteristica specifica del sistema di tipi unificato CLR. I tipi di valore contengono direttamente il relativo stato, mentre i tipi di riferimento sono una coppia implicita: l'entità denominata è un handle a un oggetto senza nome allocato nell'heap gestito. Qualsiasi inizializzazione o assegnazione di un tipo di valore a Object, ad esempio, richiede che il tipo di valore venga inserito nell'heap CLR allocando inizialmente la memoria associata, quindi copiando lo stato del tipo di valore e infine restituendo l'indirizzo di questo ibrido valore/riferimento. La scrittura in C# di

object o = 1024; // C# implicit boxing

produce pertanto effetti complessi nonostante la semplicità del codice. La progettazione di C# nasconde la complessità non solo delle operazioni eseguite, ma anche dell'astrazione del boxing. Nelle estensioni gestite per C++ viene invece evitato un falso senso di efficienza e la complessità è visibile all'utente, a cui viene richiesta un'istruzione esplicita

Object *o = __box( 1024 ); // Managed Extensions explicit boxing

La conversione boxing è implicita in Visual C++ 2010:

Object ^o = 1024; // new syntax implicit boxing

Nelle estensioni gestite la parola chiave __box offre un più importante servizio non disponibile per progettazione in linguaggi come C# e Visual Basic, ovvero fornisce un vocabolario e un handle di rilevamento per la modifica diretta di un'istanza boxed nell'heap gestito. Si consideri ad esempio il ridotto programma riportato di seguito:

int main() {
   double result = 3.14159;
   __box double * br = __box( result );

   result = 2.7; 
   *br = 2.17;   
   Object * o = br;

   Console::WriteLine( S"result :: {0}", result.ToString() ) ;
   Console::WriteLine( S"result :: {0}", __box(result) ) ;
   Console::WriteLine( S"result :: {0}", br );
}

Nel codice sottostante generato per le tre chiamate di WriteLine vengono evidenziati i diversi costi dell'accesso al valore di un tipo di valore boxed, mentre nelle righe indicate viene illustrato l'overhead associato a ogni chiamata.

// Console::WriteLine( S"result :: {0}", result.ToString() ) ;
ldstr      "result :: {0}"
ldloca.s   result  // ToString overhead
call       instance string  [mscorlib]System.Double::ToString()  // ToString overhead
call       void [mscorlib]System.Console::WriteLine(string, object)

// Console::WriteLine( S"result :: {0}", __box(result) ) ;
Ldstr    " result :: {0}"
ldloc.0
box    [mscorlib]System.Double // box overhead
call    void [mscorlib]System.Console::WriteLine(string, object)


// Console::WriteLine( S"result :: {0}", br );
ldstr    "result :: {0}"
ldloc.0
call     void [mscorlib]System.Console::WriteLine(string, object)

Passando il tipo di valore boxed direttamente a Console::WriteLine vengono eliminati sia il boxing che l'esigenza di chiamare ToString(). Poiché è presente il boxing precedente per l'inizializzazione di br, tuttavia, non si ottengono vantaggi concreti a meno che non si utilizzi effettivamente br.

Nella nuova sintassi, il supporto di tipi di valore boxed è notevolmente più integrato nel sistema di tipi, pur mantenendo la propria potenza. Di seguito è ad esempio riportata la conversione del ridotto programma precedente:

int main()
{
   double result = 3.14159;
   double^ br = result;
   result = 2.7;
   *br = 2.17;
   Object^ o = br;
   Console::WriteLine( "result :: {0}", result.ToString() );
   Console::WriteLine( "result :: {0}", result );
   Console::WriteLine( "result :: {0}", br );
}

Vedere anche

Attività

How to: Explicitly Request Boxing

Concetti

Tipi di valore e relativi comportamenti