GetType() weirdness in .NET

Following up this question on stackoverflow I stumbled across some weird issues regarding GetType().

1. GetType() cannot be overridden but hidden

While GetType() is not virtual for very good reasons and therefor one cannot override it the following is possible:

class MyClass
    public new Type GetType()
         return typeof(string);

Not that this is a good idea but it compiles and runs:

var t1 = new MyClass().GetType();
var t2 = ((object)new MyClass()).GetType();
Console.WriteLine("t1 = {0} --- t2 = {1}", t1.Name, t2.Name);

results in the expected output:

t1 = String --- t2 = MyDisposable

Now if it so important that GetType() does not violate its contract then why hasn’t there been a rule added to the specification saying that you are not allowed to new GetType(). You could argue that GetType() is just a normal method like any other – however it isn’t really. There is a lot of code relying on the fact that it does what it does and is not changed at whim, except it’s still possible to break it under certain circumstances – why not prevent it alltogether? Another argument I guess is that it would assign some special meaning for the compiler to an implemented method on the framework which certainly is not a good idea, right? Well, there are at least two exceptions out there already. One is IDisposable where an interface has a special language construct (using in C#) which relies on it. The other one is Nullable which is the only value type you can assign null to. I admit that one should be careful in what exceptions to the rule are choosen however in the case of GetType() it might have been worth it. Now the latter of the two mentioned exceptions leads me to the second weirdness.

Nullable is only sometimes null

Coming from the linked question at the top, it is apparent that the following is a bit inconsistent:

int? i = null;
Console.WriteLine(i.GetHashCode()); // works
Console.WriteLine(i.ToString()); // works
Console.WriteLine(i.HasValue); // works
Console.WriteLine(i.GetType()); // NullReferenceException

The reason being that GetType() is not virtual and is not overridden and therefor i gets boxed into object resulting in null. So a Nullable set to null does not behave like a reference type set to null when it comes to calling methods on it – except for GetType(). Why that? We have already determined that you can hide GetType() so Nullable could have done just that to and avoided the null reference problem.

Maybe someone can shed some light on why some of the decisions have been as they stand.