Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Boxing of valuetypes. Questions on size and type of boxing wrappers and valuetypes

Tags:

.net

After reading ValueTypes - RefTypes - EricLippert I have 3 questions:

Because say an 'int' derives from System.ValueType which derives from System.Object,

So how much space really does the value type like 'int' take (seeing that it finally derives from System.Object) ? Is it only size of int or the extra CLR bookkeeping fields used to distinguish it being value type.

Size difference between 'int' and 'object' ?

When 'int' is boxed with a wrapper. so is it the case that the wrapper is just an object type (and that object goes to heap) ? difference between this wrapper object and plain new object() ? how much size/space does that wrapper result to ?

like image 537
Munish Goyal Avatar asked Jun 01 '11 19:06

Munish Goyal


1 Answers

An int is 32 bits, no matter what, because it's a value.

The Object part only comes into play once you box it (for example in C# cast it to an object). Once that happens, a new object is created with everything an object has, and inside that object resides your int.

This is why C# generics are so amazing, compared to say Java, because you don't force value types into objects just to put them in a generic container, so value types are actually value types the whole time (or until the programmer gets lazy and starts throwing object val=... around).

Edit: I can understand the confusion, because of how amazing a job they did with the compiler:

var s=12.GetType(); // if it looks like an object and walks like an object...

But it is not an object, not until the GetType call, at which point the value gets boxed into an object and you invoke the virtual method on it.

It's the same with ValueType being derived from Object. Just some pretty syntactic sugar the compiler ignores and does weird things behind your back :)

edit2: Here's the dissasembled code showing the boxing:

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.Type s)
    L_0000: nop 
    L_0001: ldc.i4.s 12
    L_0003: box int32          // <---
    L_0008: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
    L_000d: stloc.0 
    L_000e: ldloc.0 
    L_000f: call void [mscorlib]System.Console::WriteLine(object)
    L_0014: nop 
    L_0015: ret 
}
like image 90
Blindy Avatar answered Oct 06 '22 06:10

Blindy