2013-10-23 14 views
6

ECMA-335, 1.8.2.4, specifica che i tipi boxable includono i tipi di riferimento (esclusi i puntatori gestiti/byrefs) e i parametri generici.Perché i tipi di riferimento di boxe?

Qual è lo scopo dei tipi di riferimento di boxe? La funzionalità e la rappresentazione della memoria di un oggetto di riferimento in scatola sono paragonabili a quelli non registrati?

+2

.NET consente di inserire un tipo di riferimento, ma C# no. Il runtime lo consente, ma tale funzionalità non verrà mai sfruttata dal compilatore C#. – Servy

+0

@Servy, come funziona in pratica, anche se ipotetico mi rendo conto. Sarebbe come 'var o = (oggetto) myRefInstance;'? È strano perché 'myRefInstance' basa già chiaramente' object'. –

+2

Inoltre, "se typeTok è un tipo di riferimento, l'istruzione box restituisce val invariato come obj" - III.4.1. –

risposta

5

Non c'è niente di logicamente sbagliato quando si inserisce un riferimento al tipo di riferimento. È solo un no-op, niente cambia.

Ma Ecma-335 non è sempre una buona descrizione di ciò che è in realtà implementato in .NET CLR. La funzione helper JIT_Box() che implementa Opcodes.Box genererà effettivamente un'eccezione InvalidCastException quando viene richiesto di inserire un valore che non è un tipo di valore. Si aspetta che un compilatore e il jitter sappiano quando sopprimere la conversione di box quando non è necessario. Loro fanno.

+0

Ma accetta un parametro generico che rappresenta un tipo di riferimento senza generare un'eccezione. In tal caso è richiesto il comportamento no-op per supportare il cast da 'T' a' object'. – CodesInChaos

+0

Questo è un punto valido. Il jitter è già a conoscenza che T è un tipo di riferimento e omette completamente il codice per la conversione di boxe. –

+0

Hai controllato se effettivamente si getta quando usi 'box' su un normale tipo di riferimento? Forse il JITter lo ottimizza anche in quel caso prima che raggiunga il codice di lancio delle eccezioni. – CodesInChaos

3

consideri la funzione generica:

object MyBox<T>(T value) 
{ 
    return (object)value; 
} 

Questo compila a:

ldarg.1  
box   01 00 00 1B 
ret 

Il comportamento atteso di questa funzione è un no-op se T è un tipo di riferimento, boxe il valore a sé .

La boxing di un valore che è noto per essere un tipo di riferimento è meno utile, ma specificarlo in modo coerente con i generici è semplice e coerente.