在C#中转换对象类型

7
我今天遇到了一个问题,但我不确定为什么它不能正常工作。
下面的代码示例会崩溃:
static void Main(string[] args)
{
     int i32 = 10;
     object obj = i32;
     long i64 = (long)obj;
}

这将导致一个InvalidCastException异常。为什么会出现这种情况?C#不聪明到足以知道对象实际上是int类型吗?

我已经想出了解决方法,但我很好奇为什么上面的代码示例一开始没有起作用。

谢谢, Tim


1
我注意到这是许多以前问题的重复,包括最近的http://stackoverflow.com/questions/3911293 - Eric Lippert
3个回答

9

无法从已装箱的Int32转换为Int64。 进行一个中间转换到int应该可以解决问题,因为编译器愿意生成以下代码:

// verify obj is a boxed int, unbox it, and perform the *statically*
// known steps necessary to convert an int to a long
long i64 = (long) ((int)obj);

但不包括(假设)这个:
// Find out what type obj *actually* is at run-time and perform 
// the-known-only-at-run-time steps necessary to produce  
// a long from it, involving *type-specific* IL instructions  
long i64 = (long)obj; 

这里是Eric Lippert关于此事的博客文章


3

请查看Eric Lippert的这篇博客文章,了解详细信息。

其要点是编译器需要通过试错来确定(因为object可以是任何类型),哪种类型被装箱以及是否可以安全地进行强制转换,这样会非常慢。


1

你是指编译器还是运行时?

运行时非常聪明,所以它会抛出InvalidCastException异常。然而,编译器无法确定你的对象的确切类型,因为你将其装箱为int。

装箱和拆箱使值类型可以被视为对象。将值类型装箱会将其封装在Object引用类型的实例中。

因此,由于它被装箱为对象,编译器不会对其进行投诉。

在此处查看有关装箱和拆箱的更多信息:

http://msdn.microsoft.com/en-us/library/yz2be5wk%28VS.80%29.aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接