Is a C # structure ever a box when using a function as the return value?

A simple question, but I did not find a definitive answer to Stack Overflow.

struct foo { int x; int y; int z; } foo Func() { return new foo(); } void Func2() { foo f = Func(); // did boxing and unboxing occur? } 

Is a C # structure (value type) always copied onto the stack when returning from a function, no matter how large it is? The reason I'm not sure is because for some sets of commands other than MSIL (e.g. x86), the return value should usually fit into the processor register, and the stack is not directly involved.

If so, is this a call site that preallocates space on the CLR stack for the type of expected return value?

[edit: Summary of responses:] For the purpose of the original question, the answer is no; The CLR will never (silently) block a structure just to send it as a return value.

+6
c # struct boxing value-type return-value
source share
2 answers

This is a tricky part of implementing a JIT compiler. In the general case, if the structure is small enough and has simple members, then it is returned to the processor registers. If it gets too large, then the calling code reserves enough space on the stack and passes a pointer to this space as an additional hidden argument.

It will never be in the box unless the return method type is an object, of course.

Fwiw: this is also the reason that the debugger cannot display the return value of the function in the Autos window. Sometimes it hurts. But the debugger does not get enough metadata from the JIT compiler to know exactly where to find the value. Edit: fixed in VS2013.

+6
source share

The structure is put into the box when you want to treat it as an object , so if you call Func and assign the result to the object, it will be put into the box.

eg. doing it

  object o = Func(); 

will give the next IL

 L_0000: call valuetype TestApp.foo TestApp.Program::Func() L_0005: box TestApp.foo L_000a: stloc.0 

which shows that the return value is inserted into the box, because we assign it a reference of type object .

If you assign it to a variable of type Foo , it does not fit into the box and is thus copied and the value is stored on the stack.

In addition, boxing will not really help you here, since it will include creating an object to represent the structure's values, and the values ​​will be effectively copied during the boxing operation.

+6
source share

All Articles