Why can't I unbox an int as a decimal?
You can only unbox a value type to its original type (and the nullable version of that type).
By the way, this is valid (just a shorthand for your two line version):
object i = 4;
decimal d = (decimal)(int)i; // works even w/o decimal as it's a widening conversion
For the reason behind this read this Eric Lippert's blog entry: Representation and Identity
Personally, I categorize things done by cast syntax into four different types of operation (they all have different IL instructions):
- Boxing (
box
IL instruction) and unboxing (unbox
IL instruction) - Casting through the inhertiance hierarchy (like
dynamic_cast<Type>
in C++, usescastclass
IL instruction to verify) - Casting between primitive types (like
static_cast<Type>
in C++, there are plenty of IL instructions for different types of casts between primitive types) - Calling user defined conversion operators (at the IL level they are just method calls to the appropriate
op_XXX
method).
There is no problem in casting an int
to decimal
, but when you are unboxing an object you have to use the exact type that the object contains.
To unbox the int
value into a decimal
value, you first unbox it as an int, then cast it to decimal:
decimal d = (decimal)(int)reader[0];
The IDataRecord interface also has methods for unboxing the value:
decimal d = (decimal)reader.GetInt32(0);
Here is a simple solution. It takes care of unboxing and then casting to decimal. Worked fine for me.
decimal d = Convert.ToDecimal(reader[0]); // reader[0] is int