我有IDataRecord reader
我正在检索小数,如下所示:
decimal d = (decimal)reader[0];
由于某种原因,这会抛出一个无效的强制转换异常,说“指定的强制转换无效。”
当我reader[0].GetType()
时,它告诉我它是Int32。据我所知,这应该不是问题......
我已经通过这个片段进行了测试,这个片段效果很好。
int i = 3750;
decimal d = (decimal)i;
这让我头疼不已,想知道为什么它没有将读取器中包含的int解包为十进制。
有谁知道为什么会这样?我有什么微妙的东西吗?
答案 0 :(得分:78)
您只能将值类型取消装箱为其原始类型(以及该类型的可空版本)。
顺便说一下,这是有效的(只是两行版本的简写):
object i = 4;
decimal d = (decimal)(int)i; // works even w/o decimal as it's a widening conversion
由于这背后的原因,请阅读此Eric Lippert's blog entry: Representation and Identity
就个人而言,我将演员语法完成的事情分为四种不同类型的操作(它们都有不同的IL指令):
box
IL指令)和拆箱(unbox
IL指令)dynamic_cast<Type>
,使用castclass
IL指令进行验证)static_cast<Type>
,对于基本类型之间的不同类型的转换,有大量的IL指令)op_XXX
方法的方法调用)。答案 1 :(得分:14)
将int
转换为decimal
没有问题,但是当您取消装箱对象时,必须使用该对象包含的确切类型。
要将int
值取消装入decimal
值,首先将其取消装箱为int,然后将其转换为小数:
decimal d = (decimal)(int)reader[0];
IDataRecord接口还具有取消装箱值的方法:
decimal d = (decimal)reader.GetInt32(0);
答案 2 :(得分:14)
这是一个简单的解决方案。它负责拆箱,然后转换为十进制。为我工作得很好。
decimal d = Convert.ToDecimal(reader[0]); // reader[0] is int
答案 3 :(得分:3)
Mehrdad Afshari说:
您只能将值类型拆分为其原始类型(以及可为空的类型) 那种类型的版本。)
要意识到的是在投射和拆箱之间存在差异。 jerryjvl有一个很好的评论
从某种意义上说,拆箱和转换语法是一种耻辱 相同,因为它们是非常不同的操作。
铸造:
int i = 3750; // Declares a normal int
decimal d = (decimal)i; // Casts an int into a decimal > OK
拳击/开箱:
object i = 3750; // Boxes an int ("3750" is similar to "(int)3750")
decimal d = (decimal)i; // Unboxes the boxed int into a decimal > KO, can only unbox it into a int or int?