Code to illustrate :
int i = 5;
object obj = i;
byte b = (byte)obj; // X
When run, this generates a System.InvalidC
MSDN explicitly says that unboxing to a different type will throw an InvalidCastException.
My understanding is that the type to which a variable is unboxed is actually a parameter to the underlying CIL assembly command. It is unbox opcode that actually throws the InvalidCastException.
InvalidCastException is thrown if the object is not boxed as valType.