2015-12-16 16 views
5
.method public static void Test<class T>(object A_0) cil managed 
{ 
    // Code size  13 (0xd) 
    .maxstack 1 
    .locals init (!!T V_0) 
    IL_0000: ldarg.0 
    IL_0001: isinst  !!T 
    IL_0006: unbox.any !!T 
    IL_000b: stloc.0 
    IL_000c: ret 
} // end of method DemoType::Test 

Der gleich C# -Code ist:CIL unbox_any Anweisung - seltsames Verhalten

public static void Test<T>(object o) where T : class 
{ 
    T t = o as T; 
} 

Meine Fragen sind:

  1. Warum unbox.any genannt? wenn Sie nur

    tun
    var a = father as child 
    

    isinst intruction rufen und keine unbox.any, und wenn ich die allgemeine Definition entfernen werde, und ich werde versuchen zu werfen (isinst), um das Objekt zu einem gewissen Klasse, keine unbox.any wird angerufen werden.

  2. Vielleicht unbox.any wurde aufgerufen, weil die generische Definition, so in diesem Fall die unbox.any eine NullReferenceException werfen müssen, weil die Antwort von isinst Anweisung null für dieses Casting zurückgibt. siehe unbox_any. Und wenn Sie versuchen, diesen Code auszuführen, werden Sie sehen, dass keine Ausnahme ausgelöst wurde.

aktualisiert

ich die unbox_any becuase den Objekttyp Parameter verstehen und es versucht, es zu konkretem Typ nach der isinst Kontrolle zu werfen. Vielleicht beeinflussen auch die Generika.

Meine Frage ist, warum nicht eine Ausnahme in unbox.any ausgelöst, wenn der Obj wir versuchen, auf T zu entpacken ist null?

Die Dokumentation sagen: "NullReferenceException wird ausgelöst, wenn Obj eine Nullreferenz ist."

+0

Kannst du erklären, was so seltsam ist? Für mich macht es Sinn. In Punkt (2) haben Sie auch keine Frage gestellt. – usr

+0

@ usr Zuerst ,, Ich möchte überprüfen, warum unbox_any aufgerufen wurde. Was für ein Gefühl, beide zu nennen? (isinst und unbox_any) Zweitens, und noch wichtiger, warum keine Ausnahme ausgelöst wird, wenn obj an unbox_any übergeben wird, ist null? –

Antwort

4

Die Unbox soll den Prüfer glücklich machen. Der Verifizierer ist nicht sonderlich schlau daran zu wissen, dass ein Typparameter T immer ein Referenztyp sein wird, und so sendet der C# -Compiler diese ansonsten unnötigen Unboxes aus.

Wenn Sie eine Suche nach dem Roslyn-Quellcode für Unbox_any und IsVerifierReference durchführen, werden Sie feststellen, dass dies an einigen Stellen im Codegenerator geschieht.

Der Jitter wird beim Generieren des Codes wissen, ob der Typparameter eine Referenz ist oder nicht und sollte anständig Code unabhängig von der scheinbar unnötigen Anweisung erzeugen.

+1

Wenn jemand daran interessiert ist, empfehle ich, [hier] (http://stackoverflow.com/questions/34382683/jitter-logic-to-remove-unbox-any?lq=1) für ein vollständiges Bild zu sehen –