0

A value type local variable (e.g. S s; given struct S{}) is initialized though the invocation of its constructor (e.g. a = new S(11)), if S declares a constructor with int parameter. Then new S(11) compiles to:

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

However when s is a field (e.g. class C { S s;), then it is not initialized in the same way. Regarding the following instance method of class C: void setS(int n) { s = new S(n); } it will compile to:

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

I was expecting that it would compile to the following code, which is more close to the case of a local variable:

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

Moreover, if I am clearly understanding, the newobj instance void S::.ctor(int32) has higher overhead and burdens GC. Am I correct?

Why, C# compiler uses for value type fields a different approach than used for local variables?

Miguel Gamboa
  • 8,855
  • 7
  • 47
  • 94
  • 1
    As Jon's correct answer notes, the optimization cannot be performed if the optimized version could produce different observable behaviour than the unoptimized version. FYI this optimization is called a "copy elision" and is common in C++ compilers; if you want to learn more about it, now you know a search term you can use. – Eric Lippert Oct 25 '17 at 17:08

1 Answers1

4

Basically, this behaviour is required in order to separate the constructor call from the assignment.

The expected observable behaviour is that if a constructor throws an exception, the assignment doesn't take place. That won't be the case in the "optimized" version where the constructor writes directly to the field/stack slot.

You can see the same IL when assigning to a local variable if:

  • The variable was already declared and assigned before
  • The variable is still accessible if an exception is thrown

Not quite the same question, but there's more detail in this SO post and on Eric Lippert's blog.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194