I'm having a hard time understanding 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 a value of Cannot unbox 'thirdTest' as a 'int'
.
What the heck is going on here?
Int16
is a fancy way to writeshort
; there is no boxing/unboxing going on there, just the plain CLR conversion between 16-bit and 32-bit integers.The second case boxes and unboxes to the same type, which is allowed: value type
int
gets wrapped in anobject
, and then gets unwrapped.The third case tries to unbox to a different type (
int
instead ofshort
) which is not allowed.What's going on is exactly what it says.
In the first case, you have a short, unboxed, that you are then explicitly typecasting to an int. This is a valid conversion that the compiler knows how to do, so it works.
In the second case, you have an int, boxed, that are are assigning back to an int. This is a simple unboxing of an integer, which also valid, so it works.
In the third case, you have a short, boxed, that are you trying to unbox into a variable that is not a short. This isn't a valid operation: you can't do this in one step. This is not an uncommon problem, either: if you are using, for example, a
SqlDataReader
that contains aSMALLINT
column, you cannot do:Either of the following should work in your third example:
Unboxing checks the exact type as explained in the documentation.
As you can see the first step is to check that the object instance matches the target type.
Also quote from the documentation:
So to fix this error make sure that the type matches before attempting to unbox: