2013-10-23 14 views
6

ECMA-335, 1.8.2.4, gibt an, dass boxfähige Typen Referenztypen (mit Ausnahme von verwalteten Zeigern/Referenzpunkten) und generische Parameter enthalten.Warum Boxen Referenztypen?

Was ist der Zweck der Boxen Referenztypen? Ist die Funktionalität und Speicherdarstellung eines Boxed-Referenzobjekts anders als das Unboxed-Objekt?

+2

In .NET kann ein Referenztyp eingerahmt werden, C# jedoch nicht. Die Laufzeitumgebung erlaubt dies, aber diese Funktionalität wird niemals vom C# -Compiler genutzt. – Servy

+0

@Servy, wie funktioniert das in der Praxis, obwohl hypothetisch ich realisiere. Wäre es wie 'var o = (object) myRefInstance;'? Es ist seltsam, weil 'myRefInstance' offensichtlich schon' object' basiert. –

+2

"Wenn TypTok ein Referenztyp ist, gibt die Box-Anweisung val unverändert als obj zurück" - III.4.1. –

Antwort

5

Es gibt nichts logisch falsch beim Einschließen eines Referenztyps. Es ist nur ein No-Op, nichts ändert sich.

Aber Ecma-335 ist nicht immer eine gute Beschreibung für was ist wirklich in der .NET CLR implementiert. Die JIT_Box() - Hilfsfunktion, die Opcodes.Box implementiert, wird tatsächlich eine InvalidCastException auslösen, wenn es aufgefordert wird, einen Wert einzubetten, der kein Werttyp ist. Es erwartet einen Compiler und der Jitter, um zu wissen, wann die Box-Konvertierung unterdrückt werden soll, wenn dies nicht notwendig ist. Tun sie.

+0

Aber es akzeptiert einen generischen Parameter, der einen Referenztyp darstellt, ohne eine Ausnahme auszulösen. In diesem Fall ist das Nicht-Op-Verhalten erforderlich, um das Gießen von "T" zu "Objekt" zu unterstützen. – CodesInChaos

+0

Das ist ein gültiger Punkt. Der Jitter ist sich bereits bewusst, dass T ein Referenztyp ist und lässt den Code für die Box-Konvertierung komplett weg. –

+0

Haben Sie überprüft, ob es tatsächlich ausgelöst wird, wenn Sie 'box' für einen normalen Referenztyp verwenden? Vielleicht optimiert der JITter es auch in diesem Fall, bevor es den Exception-Throw-Code erreicht. – CodesInChaos

3

Betrachten Sie die generische Funktion:

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

Dies kompiliert zu:

ldarg.1  
box   01 00 00 1B 
ret 

Das erwartete Verhalten dieser Funktion ist ein no-op, wenn T ein Referenztyp ist, den Wert selbst Box .

Einen Wert zu boxen, der bekanntermaßen ein Referenztyp ist, ist weniger nützlich, aber die Angabe in einer Weise, die mit Generika konsistent ist, ist einfach und konsistent.