Value types have smaller memory footprint since they are not allocated on the managed heap, and as such does not have the additional fields – sync block index and type handle – and no reference to the field exists. Also not being a reference type, it does not get garbage collected. However, value types can exist on a threads stack or as a field in a managed type on the managed heap.
Sometimes we must convert a value type to a reference type. For this to work, the value type must be boxed. Here is what happens when a value type is boxed:
- The size of the new object is calculated. That includes the two overhead members all reference types have. Then memory is allocated on the managed heap.
- The value types members are copied to the new managed heap allocated memory.
- An address to the new reference type is now returned. The value type is now a reference type.
Unboxing is pretty much the opposite steps:
- If the reference to the value type is null, a NullReferenceException is thrown.
- If the reference is of the wrong type, an InvalidCastException is thrown.
- A pointer to the value type inside the managed object is returned.
When unboxing the cast must be to the correct type.
An unboxing operation is typically followed-up by a copy operation. This copies the fields from the boxed object to the value type.
An C# example of boxing and unboxing. It’s important to be aware that C# automatically emits code to box and unbox objects.
long z = 4; object o = z; // boxing int f = (int)o; // InvalidCastException long s = (long)o; // Unboxing.