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开发者_JAVA技巧 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 ?
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
I think the reason is that GetHashCode is implemented on System.Int32 directly, you call System.Int32::GetHashCode(). No need to box if you call a known member function on a value type.
Seems very close to How is ValueType.GetType() able to determine the type of the struct?
Also related is GetType and TypeOf confusion
精彩评论