views:

439

answers:

2

Quoting from the MSDN Link for ValueType Class

In cases where it is necessary for a value type to behave like an object, a wrapper that makes the value type look like a reference object is allocated on the heap, and the value type's value is copied into it. The wrapper is marked so the system knows that it contains a value type.

This means when I code like "integerVariable.ToString();" a wrapper-object created allows using this method and similarly all the other methods of System.Object.

Is this understanding correct?

How are these objects different from the 'regular' objects?

Is the Garbage Collection different for such object? If yes, how?

Thanks in advance.

+1  A: 

Yes that understanding is correct.

These objects are no different from 'regular' objects in the CLR.

Since these objects (also called 'boxes' becuase they wrap value types) are just like any other object the garbage collector is the same too.

Frederick
Not quite correct; calling ToString() doesn't create a box if the method is overridden, which it usually is.
Marc Gravell
+5  A: 

The wrapper is a "box"; re garbage collection of boxes - there is no difference as far as the grabage collector is concerned. A box is collected with exactly the same rules and treatment as any other object.

however, if a value-type overrides a method (such as ToString()), it is not necessary to box it to call the method. Hence, value-types should (as a matter of routine) override as many of the object methods as possible ;-p

You can see the difference in the IL (via reflector) - so for the C#:

static int GetInteger() {return 123;}
static string TestToString() {
    int i = GetInteger(); // to prove no cheating
    return i.ToString();
}
static Type TestGetType() {
    int i = GetInteger(); // to prove no cheating
    return i.GetType();
}

We have the IL:

.method private hidebysig static string TestToString() cil managed
{
    .maxstack 1
    .locals init (
        [0] int32 i)
    L_0000: call int32 Program::GetInteger()
    L_0005: stloc.0 
    L_0006: ldloca.s i
    L_0008: call instance string [mscorlib]System.Int32::ToString()
    L_000d: ret 
}

.method private hidebysig static class [mscorlib]System.Type TestGetType() cil managed
{
    .maxstack 1
    .locals init (
        [0] int32 i)
    L_0000: call int32 Program::GetInteger()
    L_0005: stloc.0 
    L_0006: ldloc.0 
    L_0007: box int32
    L_000c: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
    L_0011: ret 
}

Note that ToString() doesn't involve a box, but GetType() does at L_0007 (since it isn't (can't be) overridden)

Marc Gravell
+1 great answer ;)
bruno conde