Если вы компилируете
object o = null;
int a = (int)o;
и посмотрите код MSIL, вы увидите что-то вроде
ldnull
...
unbox.any int32
Теперь поведение unbox.any определяется следующим образом:
InvalidCastException выдается, если объект
не в штучной упаковке.
NullReferenceException генерируется, если
obj является пустой ссылкой.
Это то, что вы видите в своем коде.