为什么我不能将int取消装入十进制?

时间:2022-04-03 12:52:51

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

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

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....

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

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.

这让我头疼不已,想知道为什么它没有将读取器中包含的int取消装箱作为小数。

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

有谁知道为什么会这样?有什么微妙的我不见了吗?

4 个解决方案

#1


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

由于这背后的原因,请阅读Eric Lippert的博客文章:Representation and Identity

Personally, I categorize things done by cast syntax into four different types of operation (they all have different IL instructions):

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

  1. Boxing (box IL instruction) and unboxing (unbox IL instruction)
  2. 拳击(框IL指令)和拆箱(unbox IL指令)

  3. Casting through the inhertiance hierarchy (like dynamic_cast<Type> in C++, uses castclass IL instruction to verify)
  4. 通过inhertiance层次结构进行转换(如C ++中的dynamic_cast ,使用castclass IL指令进行验证)

  5. Casting between primitive types (like static_cast<Type> in C++, there are plenty of IL instructions for different types of casts between primitive types)
  6. 在原始类型之间进行转换(比如C ++中的static_cast ,对于基本类型之间的不同类型的转换,有大量的IL指令)

  7. Calling user defined conversion operators (at the IL level they are just method calls to the appropriate op_XXX method).
  8. 调用用户定义的转换运算符(在IL级别,它们只是对相应op_XXX方法的方法调用)。

#2


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.

将int转换为十进制没有问题,但是当您取消装箱对象时,必须使用该对象包含的确切类型。

To unbox the int value into a decimal value, you first unbox it as an int, then cast it to decimal:

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

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

The IDataRecord interface also has methods for unboxing the value:

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

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

#3


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

#4


Mehrdad Afshari said it:

Mehrdad Afshari说:

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?

#1


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

由于这背后的原因,请阅读Eric Lippert的博客文章:Representation and Identity

Personally, I categorize things done by cast syntax into four different types of operation (they all have different IL instructions):

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

  1. Boxing (box IL instruction) and unboxing (unbox IL instruction)
  2. 拳击(框IL指令)和拆箱(unbox IL指令)

  3. Casting through the inhertiance hierarchy (like dynamic_cast<Type> in C++, uses castclass IL instruction to verify)
  4. 通过inhertiance层次结构进行转换(如C ++中的dynamic_cast ,使用castclass IL指令进行验证)

  5. Casting between primitive types (like static_cast<Type> in C++, there are plenty of IL instructions for different types of casts between primitive types)
  6. 在原始类型之间进行转换(比如C ++中的static_cast ,对于基本类型之间的不同类型的转换,有大量的IL指令)

  7. Calling user defined conversion operators (at the IL level they are just method calls to the appropriate op_XXX method).
  8. 调用用户定义的转换运算符(在IL级别,它们只是对相应op_XXX方法的方法调用)。

#2


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.

将int转换为十进制没有问题,但是当您取消装箱对象时,必须使用该对象包含的确切类型。

To unbox the int value into a decimal value, you first unbox it as an int, then cast it to decimal:

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

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

The IDataRecord interface also has methods for unboxing the value:

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

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

#3


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

#4


Mehrdad Afshari said it:

Mehrdad Afshari说:

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?