.NET Primitive types implementation-Collection of common programming errors
It depends on the glasses you wear. If you have “implementation” glasses then you’ll see that any reference type value has an object header. Which makes them inherit System.Object. The object header has two fields, the sync-block that stores various bits of info like the hash code and the thread ID that called Monitor.Enter(). The important field is the second one, the method table pointer. Which identifies the object type. The method table contains the addresses of the methods of the class, it will always start off with Equals, GetHashCode and ToString, the methods that Object implemnts.
Wearing those same glasses, a value type value does not have this object header. It only occupies the amount of space required to store the value. One byte for a bool, two bytes for a Char, four bytes for an int, etcetera. Which makes value types very efficient.
The second pair of glasses you can put on are the “type system” glasses. A value type value can always be converted to an object. And back. This conversion is called the boxing conversion. Going back is called unboxing. Pop on the implementation glasses real quick and you’ll see that you indeed get an object with those two fields, the method table pointer identifies the value type. The method table has additional method pointers. Like those for IConvertible, an interface implemented by value types. The rest of the object, beyond those two fields, is occupied by the value type value bits. The same bits it had when it was still a simple value before the boxing conversion. And the boxed object lives on the garbage collected heap, just like all reference type objects.
In the vast majority of cases, the C# or VB.NET compiler applies the boxing conversion completely automatically. You don’t have to write a cast in your code yourself. You can for example call ToString or one of the IConvertible methods and you’ll get the boxing conversion for free.
This creates the illusion that a value type inherits from System.Object. It is a pretty decent illusion, anybody wearing “type system” glasses will insist that a value type absolutely inherits from Object. If you wear “implementation” glasses then you tend to worry a bit about the boxing. It is heavily optimized but it certainly isn’t for free. It costs cpu cycles to make the conversion and a boxed value type value takes a lot more space and creates garbage. One of the reasons that the generic collection types have completely replaced the old System.Collection classes.