C # - Problems with boxing / unboxing / typecasting ints. I do not understand

It’s hard for me to understand this. Consider the following example:

protected void Page_Load(object sender, EventArgs e) { // No surprise that this works Int16 firstTest = Convert.ToInt16(0); int firstTest2 = (int)firstTest; // This also works object secondTest = 0; int secondTest2 = (int)secondTest; // But this fails! object thirdTest = Convert.ToInt16(0); int thirdtest2 = (int)thirdTest; // It blows up on this line. } 

The specific error that I get at runtime is Specified cast is not valid. If I QuickWatch (int)thirdTest in Visual Studio, I get Cannot unbox 'thirdTest' as a 'int' value.

What's going on here?

+8
casting c # boxing
source share
3 answers

Unboxing checks the exact type as described in the documentation .

Unboxing is an explicit conversion from a type object to a type value, or from an interface type to a value type that implements an interface. The unboxing operation consists of:

  • Checking an instance of an object to make sure that the value in the box is the given value type.

  • Copy a value from an instance to a value type variable.

As you can see, the first step is to verify that the object instance matches the target type.

Also indicate from the documentation:

To unpack value types that will succeed at run time, an unboxed element must be a reference to an object that was previously created by boxing an instance of this value type. An unbox null attempt throws a NullReferenceException. An attempt to remove a reference to an incompatible value type raises an InvalidCastException.

So, to fix this error, make sure that the type is mapped before trying to unpack:

 object thirdTest = Convert.ToInt16(0); short thirdtest2 = (short)thirdTest; 
+12
source share

What happens is exactly what he says.

In the first case, you have a short, unboxed, which is then explicitly assigned to the int method. This is the correct conversion that the compiler knows how to do, so it works.

In the second case, you have int, boxed, which assign an int int. This is a simple unpacking of an integer that also works, so it works.

In the third case, you have a short one in the box that you are trying to unpack into a variable that is not short. This is not a valid operation: you cannot do it in one step. This is not an unusual problem: if you use, for example, SqlDataReader , which contains a SMALLINT column, you cannot do:

  int x = (int)rdr["SmallIntColumn"]; 

Any of the following should work in your third example:

  object thirdTest = Convert.ToInt16(0); int thirdTest2 = Convert.ToInt32(thirdTest); int thirdTest3 = (int)(short)thirdTest; 
+9
source share

Int16 is a fantastic way to write short ; there is no boxing / unboxing, just a simple CLR conversion between 16-bit and 32-bit integers.

Codes and boxes for the second case for the same type that are allowed: the int value type ends with object and then unpacks.

The third case tries to unpack to another type ( int instead of short ), which is not allowed.

+4
source share

All Articles