为什么我不能取消一个int作为小数?
我有一个IDataRecord reader
,我正在检索一个小数,如下所示:
decimal d = (decimal)reader[0];
由于某种原因,这会抛出一个无效的转换exception,说“指定的转换无效”。
当我做reader[0].GetType()
它告诉我,它是一个Int32。 据我所知,这不应该是一个问题….
我已经testing了这个片段,这工作得很好。
int i = 3750; decimal d = (decimal)i;
这让我挠脑袋,想知道为什么它不能将读取器中包含的int作为十进制数来打开。
有谁知道为什么这可能会发生? 我错过了些微妙的东西吗?
您只能将值types取消为原始types(以及该types的可为空的版本)。
顺便说一句,这是有效的(只是你的两行版本的简写):
object i = 4; decimal d = (decimal)(int)i; // works even w/o decimal as it's a widening conversion
为此,请阅读Eric Lippert的博客文章:表示和身份
就我个人而言,我将通过强制语法完成的事情分为四种不同types的操作(它们都有不同的IL指令):
- 拳击(
box
IL指令)和拆箱(unbox
IL指令) - 通过inhertiance层次结构(如C ++中的
dynamic_cast<Type>
,使用castclass
IL指令进行validation) - 在原始types之间进行转换(如C ++中的
static_cast<Type>
,对于原始types之间的不同types的转换,有很多IL指令) - 调用用户定义的转换运算符(在IL级别,他们只是方法调用适当的
op_XXX
方法)。
将int
为decimal
是没有问题的,但是当你拆箱的时候,你必须使用对象所包含的确切types。
要将int
值解包为一个decimal
值,您首先将其解包为一个int,然后将其转换为十进制:
decimal d = (decimal)(int)reader[0];
IDataRecord接口也有拆箱的方法:
decimal d = (decimal)reader.GetInt32(0);
这是一个简单的解决scheme。 它需要照顾拆箱,然后铸造到十进制。 为我工作得很好。
decimal d = Convert.ToDecimal(reader[0]); // reader[0] is int
Mehrdad Afshari说:
您只能将值types取消为原始types(以及该types的可为空的版本)。
要实现的事情是铸造和拆箱是有区别的 。 杰里耶夫有一个很好的评论
从某种意义上说,拆箱和铸造在句法上看起来是完全相同的,因为它们是非常不同的操作。
铸件:
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?