Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to cast a boxed int to byte

Code to illustrate :

        int i = 5;
        object obj = i;
        byte b = (byte)obj; // X

When run, this generates a System.InvalidCastException ("Specified cast is not valid") at line "X". Doing a double cast works :

        byte b = (byte)(int)obj;

I would have thought that you ought to be able to cast a boxed int (if it has a value in the range 0..255) to a byte. Can anyone shed any light on this ?

(This is in .net 2.0, in case that matters).

like image 371
Moe Sisko Avatar asked Jun 04 '10 01:06

Moe Sisko


2 Answers

The difference in behaviour you're seeing is the difference between identity and representation.

Unboxing is an identity cast, and a representation-preserving operation. Casting an int to a byte, however, is representation-changing (since there is a potential loss of precision).

You get an InvalidCastException when you try to unbox the int as a byte because the identity of the boxed value is not a byte, it is an int. When you write byte b = (byte)obj, you are telling the runtime, I know that what's in there is a byte, but what you really mean to say is, I think that what's in there can be converted to a byte.

In order to make the latter statement, you first have to declare the identity of the object, which is an int. Then and only then can you make a representation-changing conversion to byte.

Note that this applies even if the target type is "larger" - i.e. an Int64. All explicit conversions for which the destination type is not in the inheritance tree of the source type are considered to be representation-changing. And since all types derive from System.Object, unboxing by definition cannot change the representation.

like image 91
Aaronaught Avatar answered Sep 24 '22 15:09

Aaronaught


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.

like image 37
Igor Zevaka Avatar answered Sep 23 '22 15:09

Igor Zevaka