2010-10-13 52 views
9

好吧我必须俯视一些非常简单的东西,但我迷路了。混淆拳击。投1到Int64抛出InvalidCastException

鉴于这种

object val = -1; 
var foo = (Int32)(val); 
var bar = (Int64)(val); 

演员到Int64的抛出和InvalidCastException的。

我认识到这与拳击的一些奇怪有关,但我不明白推理。

从我的理解val被装箱为Int32在第一行。

然后,当我尝试抛出Int32以外的其他东西时抛出InvalidCastException。我想这意味着我试图取消将val作为Int64,当它实际上是一个Int32?

还是显得很奇怪。无法将演员取消装箱值然后尝试执行演员?

喜欢的东西(很明显,这是可怕的过于简单,也许盒装类型是不知道,所以这是不可能的?):

object val = -1; 
Int32 unboxed = (Int32)(val); 
var bar = (Int64)(unboxed); 

有人(读:埃里克利珀)学校我的背后的原因这个。

UPDATE:从Eric的博客,里德公布的链接,这是简洁的答案我一直在寻找

” ......这将是一个巨大的代码来生成量,这将是非常慢,代码当然是非常大的,你可能想要把它放在自己的方法中,只需要调用它就可以了,而不是默认的,并且总是生成缓慢,大而脆弱的代码,而不是使用代码我们已经决定拆箱只能取消确切的类型如果你想调用缓慢的方法来完成所有的工作,它就可以了 - 你可以随时调用Convert.ToInt32,它可以在运行时进行所有的分析 为你。我们给你选择“快速和准确”或“慢慢和松懈”,明智的默认是前者。如果你想要后者然后调用方法....“

+0

这是后话。非常不模拟PLE。它绊倒了很多人... – 2010-10-13 18:20:23

+0

里德是对的;这在SO上每周会被询问几次。它昨天被问了两次。 – 2010-10-14 14:04:28

+0

所以,我很明显地提出一个问题,就是询问其他人询问的问题,而不是先搜索。我觉得有趣的是,如果这是一个普遍的问题,那么它仍然会得到6票。显然,默认行为并不是最明显的行为。 – 2010-10-15 20:59:38

回答

15

这是因为你不能在一个单独的操作中取消装箱和执行转换,你必须将Int32的值解开到Int32中,然后转换。它的类型

正因为如此,这需要拆箱的对象,然后再转换为Int64的:

object val = -1; 
int foo = (Int32)val; 
Int64 bar = (Int64)(Int32)val; 

埃里克利珀覆盖对此进行了详细在他的题为Representation and Identity博客文章

+0

太棒了,Eri​​c Lippert通过代理:)你摇滚 – 2010-10-13 18:31:08

+0

另一种写法:'Int64 a = -1;对象o = a; Int64 b =(Int64)o;'谢谢里德! – Nayan 2010-10-13 18:32:41

+0

难道人们请不要说*转换*当他们的意思*转换*?整数类型之间不存在“转换”;他们正在*转换*。(不幸的是,C#对这两种语法都使用相同的语法。) – Timwi 2010-10-13 18:39:33