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?
Unboxing checks the exact type as explained in the documentation.
Unboxing is an explicit conversion from the type object to a value type or from an interface type to a value type that implements the interface. An unboxing operation consists of:
Checking the object instance to make sure that it is a boxed value of the given value type.
Copying the value from the instance into the value-type variable.
As you can see the first step is to check that the object instance matches the target type.
Also quote from the documentation:
For the unboxing of value types to succeed at run time, the item being unboxed must be a reference to an object that was previously created by boxing an instance of that value type. Attempting to unbox null causes a NullReferenceException. Attempting to unbox a reference to an incompatible value type causes an InvalidCastException.
So to fix this error make sure that the type matches before attempting to unbox:
object thirdTest = Convert.ToInt16(0);
short thirdtest2 = (short)thirdTest;
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 a SMALLINT
column, you cannot do:
int x = (int)rdr["SmallIntColumn"];
Either of the following should work in your third example:
object thirdTest = Convert.ToInt16(0);
int thirdTest2 = Convert.ToInt32(thirdTest);
int thirdTest3 = (int)(short)thirdTest;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With