【问题标题】:Confused by Boxing. Casting -1 to Int64 throws InvalidCastException被拳击迷惑了。将 -1 转换为 Int64 会引发 InvalidCastException
【发布时间】:2011-04-25 00:12:23
【问题描述】:

好吧,我一定是忽略了一些非常简单的事情,但我迷路了。

鉴于此

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

有人(阅读:Eric Lippert)向我学习这背后的原因。

更新: Reed 在 Eric 的博客中发布了指向此链接的链接,这是我一直在寻找的简洁答案

"...这将是大量的代码要生成,而且会非常慢。代码当然很大,你可能想把它放在它自己的方法中,然后生成一个调用它。而不是默认这样做,并且总是生成缓慢、大而脆弱的代码,相反,我们决定拆箱只能拆箱到确切的类型。如果你想调用可以做所有这些事情的慢速方法,它是可用的——你总是可以调用 Convert.ToInt32,它会在运行时为你做所有的分析。我们让你在“快速和精确”或“缓慢和松懈”之间进行选择,并且明智的默认是前者。如果你想要后者然后调用方法...."

【问题讨论】:

  • 这是非常不简单的事情。它绊倒了很多人......
  • 里德是对的;每周都会在 SO 上多次询问这个问题。昨天被问了两次。
  • 所以,我显然很蹩脚,因为我问了其他人问的同样的问题,而不是先搜索。我觉得有趣的是,如果这是一个如此常见的问题,这仍然得到 6 票赞成。显然默认行为并不是最明显的行为。

标签: c# .net language-design language-features


【解决方案1】:

这是因为您无法在一次操作中拆箱并执行转换。您必须将 Int32 值拆箱为 Int32,然后再转换其类型。

因此,这需要将对象拆箱,然后转换为 Int64:

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

Eric Lippert 在他题为 Representation and Identity 的博文中详细介绍了这一点。

【讨论】:

  • 太棒了,Eri​​c Lippert by proxy :) 你摇滚
  • 另一种写法:Int64 a = -1; object o = a; Int64 b = (Int64)o; 谢谢 Reed!
  • 当人们的意思是 conversion 时,请不要再说 cast 吗?整数类型之间没有“强制转换”;他们正在被转换。 (不幸的是,C# 对两者使用相同的语法。)
  • @Timwi:我同意你的观点,但你正在打一场艰苦的战斗。我更喜欢保留“转换”来表示代码中转换运算符的实际编译时文本,而“转换”表示将一种类型转换为另一种类型的运行时操作。但大多数人并没有做出这种区分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
相关资源
最近更新 更多