public class MyClass { public int Age; public int ID; } public void MyMethod() { MyClass m = new MyClass(); int newID; }
To my understanding, the following is true:
- The reference m lives on the stack and goes out of scope when MyMethod() exits.
- The value type newID lives on the stack and goes out of scope when MyMethod() exits.
- The object created by the new operator lives in the heap and becomes reclaimable by the GC when MyMethod() exits, assuming no other reference to the object exists.
Here is my question:
- Do value types within objects live on the stack or the heap?
- Is boxing/unboxing value types in an object a concern?
- Are there any detailed, yet understandable, resources on this topic?
Logically, I’d think value types inside classes would be in the heap, but I’m not sure if they have to be boxed to get there.
Edit:
Suggested reading for this topic:
Value-type values for a class have to live together with the object instance in the managed heap. The thread’s stack for a method only lives for the duration of a method; how can the value persist if it only exists within that stack?
A class’ object size in the managed heap is the sum of its value-type fields, reference-type pointers, and additional CLR overhead variables like the Sync block index. When one assigns a value to an object’s value-type field, the CLR copies the value to the space allocated within the object for that particluar field.
Take for example, a simple class with a single field.
And with it, a simple testing class.
If you use the MSIL Disassembler provided by the .NET Framework SDK to peek at the IL code for EmbeddedTest.TestEmbeddedValues()
Notice the CLR is being told to stfld the loaded value of ’20’ in the stack to the loaded EmbeddValues’ NumberField field location, directly into the managed heap. Similarly, when retrieving the value, it uses ldfld instruction to directly copy the value out of that managed heap location into the thread stack. No box/unboxing happens with these types of operations.