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指令):
- Boxing (
box
IL instruction) and unboxing (unbox
IL instruction) - Casting through the inhertiance hierarchy (like
dynamic_cast<Type>
in C++, usescastclass
IL instruction to verify) - Casting between primitive types (like
static_cast<Type>
in C++, there are plenty of IL instructions for different types of casts between primitive types) - Calling user defined conversion operators (at the IL level they are just method calls to the appropriate
op_XXX
method).
拳击(框IL指令)和拆箱(unbox IL指令)
通过inhertiance层次结构进行转换(如C ++中的dynamic_cast
在原始类型之间进行转换(比如C ++中的static_cast
调用用户定义的转换运算符(在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指令):
- Boxing (
box
IL instruction) and unboxing (unbox
IL instruction) - Casting through the inhertiance hierarchy (like
dynamic_cast<Type>
in C++, usescastclass
IL instruction to verify) - Casting between primitive types (like
static_cast<Type>
in C++, there are plenty of IL instructions for different types of casts between primitive types) - Calling user defined conversion operators (at the IL level they are just method calls to the appropriate
op_XXX
method).
拳击(框IL指令)和拆箱(unbox IL指令)
通过inhertiance层次结构进行转换(如C ++中的dynamic_cast
在原始类型之间进行转换(比如C ++中的static_cast
调用用户定义的转换运算符(在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?