我有一个 IDataRecord reader 我正在检索小数,如下所示:

decimal d = (decimal)reader[0];

由于某种原因,这会引发无效的强制转换异常,指出“指定的强制转换无效”。

当我做 reader[0].GetType() 它告诉我它是一个 Int32。据我所知,这应该不是问题......

我已经通过这个片段进行了测试,效果很好。

int i = 3750;
decimal d = (decimal)i;

这让我摸不着头脑,想知道为什么它无法将读取器中包含的 int 拆箱为十进制。

有谁知道为什么会发生这种情况?我缺少什么微妙的东西吗?

有帮助吗?

解决方案

您只能将值类型取消装箱为其原始类型(以及该类型的可为空版本)。

顺便说一句,这是有效的(只是两行版本的简写):

object i = 4;
decimal d = (decimal)(int)i; // works even w/o decimal as it's a widening conversion

对于这背后的原因请阅读此内容 埃里克·利珀特的博客条目:代表和身份

就我个人而言,我将强制转换语法完成的操作分为四种不同类型的操作(它们都有不同的 IL 指令):

  1. 拳击(box IL指令)和拆箱(unbox IL指令)
  2. 通过继承层次结构进行转换(例如 dynamic_cast<Type> 在 C++ 中,使用 castclass IL指令验证)
  3. 原始类型之间的转换(例如 static_cast<Type> 在 C++ 中,有大量用于基本类型之间不同类型转换的 IL 指令)
  4. 调用用户定义的转换运算符(在 IL 级别,它们只是对适当的方法的调用) op_XXX 方法)。

其他提示

有在铸造intdecimal没有问题的,但是当你拆箱一个目的必须使用的确切类型,所述对象包含。

要拆箱int值成decimal值,则第一拆箱它作为int,然后将它转换为十进制:

decimal d = (decimal)(int)reader[0];

在IDataRecord接口还具有用于取消装箱的值的方法:

decimal d = (decimal)reader.GetInt32(0);

下面是一个简单的解决方案。它负责拆箱,然后浇铸成十进制。工作对我罚款。

decimal d = Convert.ToDecimal(reader[0]);  // reader[0] is int

迈赫达德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?
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top