Search code examples
c#.net.net-internals

Why calling some functions of the Object class, on a primitive type instance, need boxing?


I have discovered that if i run following lines of code.

int i = 7;
i.GetHashCode(); //where GetHashCode() is the derived
                 //function from System.Object

No boxing is done, but if i call i.GetType() (another derived function from System.Object) in place of GetHashCode(), a boxing will be required to call GetType(), Why its not possible to call GetType() on primitive type instance directly, without boxing, while its possible to call GetHashCode() without boxing ?


Solution

  • The key here is that GetType() is not virtual and cannot be overridden. Since a struct is effectively sealed, methods cannot be overridden any more than the struct, so the runtime and compiler can treat struct methods that have been overridden as static calls.

    If you write a struct (rare) you should override all the methods like ToString(), Equals(), GetHashCode() for exactly this reason. If you don't it must box. However, GetType() cannot be overridden, thus needs boxing.

    This actually leads to some odd edge-cases with Nullable<T> and boxing, since an empty Nullable<T> boxes to null, so:

    int i = obj.GetHashCode(); // fine
    Type t = obj.GetType(); // boom