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:
Here is my question:
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:
Two Parts of Memory In short, value types are stored in the Stack and reference types are stored in the Heap.
While value types are stored generally in the stack, reference types are stored in the managed heap. A value type derives from System. ValueType and contains the data inside its own memory allocation.
In C# there are two places where an object can be stored -- the heap and the stack. Objects allocated on the stack are available only inside of a stack frame (execution of a method), while objects allocated on the heap can be accessed from anywhere.
A value type stores its contents in memory allocated in the stack, so we can say value types are allocated in the stack in Swift. ? The misconception is that most people think value types are always stored in the Stack. Value types can be stored inside the stack when they are either temporary or local variables.
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.
public class EmbeddedValues
{
public int NumberField;
}
And with it, a simple testing class.
public class EmbeddedTest
{
public void TestEmbeddedValues()
{
EmbeddedValues valueContainer = new EmbeddedValues();
valueContainer.NumberField = 20;
int publicField = valueContainer.NumberField;
}
}
If you use the MSIL Disassembler provided by the .NET Framework SDK to peek at the IL code for EmbeddedTest.TestEmbeddedValues()
.method public hidebysig instance void TestEmbeddedValues() cil managed
{
// Code size 23 (0x17)
.maxstack 2
.locals init ([0] class soapextensions.EmbeddedValues valueContainer,
[1] int32 publicField)
IL_0000: nop
IL_0001: newobj instance void soapextensions.EmbeddedValues::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.s 20
IL_000a: stfld int32 soapextensions.EmbeddedValues::NumberField
IL_000f: ldloc.0
IL_0010: ldfld int32 soapextensions.EmbeddedValues::NumberField
IL_0015: stloc.1
IL_0016: ret
} // end of method 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With