为什么我不能将 int 拆箱为十进制?

发布于 2024-07-26 08:39:46 字数 417 浏览 4 评论 0原文

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

decimal d = (decimal)reader[0];

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

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

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

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

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

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

I have an IDataRecord reader that I'm retrieving a decimal from as follows:

decimal d = (decimal)reader[0];

For some reason this throws an invalid cast exception saying that the "Specified cast is not valid."

When I do reader[0].GetType() it tells me that it is an Int32. As far as I know, this shouldn't be a problem....

I've tested this out by this snippet which works just fine.

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

This has left me scratching my head wondering why it is failing to unbox the int contained in the reader as a decimal.

Does anyone know why this might be occurring? Is there something subtle I'm missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧话新听 2024-08-02 08:39:46

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

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

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

出于这背后的原因,请阅读此 Eric Lippert 的博客文章:表示和身份

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

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

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):

  1. Boxing (box IL instruction) and unboxing (unbox IL instruction)
  2. Casting through the inhertiance hierarchy (like dynamic_cast<Type> in C++, uses castclass IL instruction to verify)
  3. Casting between primitive types (like static_cast<Type> in C++, there are plenty of IL instructions for different types of casts between primitive types)
  4. Calling user defined conversion operators (at the IL level they are just method calls to the appropriate op_XXX method).
吃→可爱长大的 2024-08-02 08:39:46

int 转换为 decimal 没有问题,但是当您拆箱对象时,您必须使用该对象包含的确切类型。

要将 int 值拆箱为 decimal 值,首先将其拆箱为 int,然后将其转换为十进制:

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

IDataRecord 接口还具有拆箱该值的方法:

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

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);
萌化 2024-08-02 08:39:46

这是一个简单的解决方案。 它负责拆箱然后转换为十进制。 对我来说效果很好。

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

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
慕巷 2024-08-02 08:39:46

迈赫达德·阿夫沙里说道:

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

需要意识到的是铸造和拆箱之间是有区别的。 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?

Mehrdad Afshari said it:

You can only unbox a value type to its original type (and the nullable
version of that type).

The thing to realize is that there is a difference between casting and unboxing. jerryjvl had an excellent remark

In a sense it's a shame that unboxing and casting syntactically look
identical, since they are very different operations.

Casting:

int i = 3750; // Declares a normal int
decimal d = (decimal)i; // Casts an int into a decimal > OK

Boxing/Unboxing:

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?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文