2017-10-25 5 views
0

Eine Werttyp lokale Variable (z. B. S s; gegeben struct S{}) wird durch den Aufruf seines Konstruktors initialisiert (z. B. a = new S(11)), wenn S einen Konstruktor mit int Parameter deklariert. Dann new S(11) kompiliert:Warum Werttyp-Felder instanziiert werden können, anstatt initialisiert?

ldloca.s V_0 
ldc.i4.s 11 
call  instance void S::.ctor(int32) 

Wenn jedoch s ein Feld (z.B. class C { S s;) ist, dann ist sie nicht in der gleichen Weise initialisiert. In Bezug auf die folgende Instanzmethode der Klasse C: void setS(int n) { s = new S(n); } es kompiliert:

ldarg.0 
ldarg.1 
newobj  instance void S::.ctor(int32) 
stfld  valuetype S C::s 

Ich habe erwartet, dass es mit dem folgenden Code kompilieren würde, die mehr in der Nähe des Fall einer lokalen Variablen ist:

ldarg.0 
ldflda valuetype S C::s 
ldarg.1 
call  instance void S::.ctor(int32) 

Darüber hinaus, wenn ich klar verstehe, hat die newobj instance void S::.ctor(int32) höhere Overhead und Belastungen GC. Hab ich recht?

Warum verwendet der C# -Compiler für Werttypfelder einen anderen Ansatz als für lokale Variablen?

+1

Wie Jons korrekte Antwort feststellt, kann die Optimierung nicht durchgeführt werden, wenn die optimierte Version ein anderes beobachtbares Verhalten als die nicht optimierte Version hervorbringen könnte. Zur Erinnerung: Diese Optimierung wird als "copy elision" bezeichnet und ist in C++ - Compilern üblich. Wenn Sie mehr darüber erfahren möchten, kennen Sie jetzt einen Suchbegriff, den Sie verwenden können. –

Antwort

4

Dieses Verhalten ist im Prinzip erforderlich, um den Konstruktoraufruf von der Zuweisung zu trennen.

Das erwartete beobachtbare Verhalten ist, dass, wenn ein Konstruktor eine Ausnahme auslöst, die Zuweisung nicht stattfindet. Dies wird in der "optimierten" Version nicht der Fall sein, in der der Konstruktor direkt in den Feld-/Stapel-Slot schreibt.

können Sie die gleiche IL sehen, wenn zu einer lokalen Variablen zugewiesen wird, wenn:

  • Die Variable bereits vor
  • erklärt und zugewiesen wurde Die Variable ist immer noch zugänglich, wenn eine Ausnahme ausgelöst wird

Nicht ganz die gleiche Frage, aber es gibt mehr Details in this SO post und Eric Lippert's blog.

Verwandte Themen