2010-10-12 138 views
7

今天我遇到了一个问题,我不完全确定它为什么不起作用。在c中铸造对象类型#

下面的代码示例会崩溃:

static void Main(string[] args) 
{ 
    int i32 = 10; 
    object obj = i32; 
    long i64 = (long)obj; 
} 

这将导致一个InvalidCastException。为什么这不起作用? C#没有足够的智能来知道对象实际上是int类型的吗?

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

感谢, 添

+1

我注意到这是许多以前的问题的重复,包括最近http://stackoverflow.com/questions/3911293 – 2010-10-13 05:18:47

回答

9

没有为Int64没有可用的铸从盒装的Int32。 使中间投地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; 

这里有一个blog post通过埃里克利珀这一点。

1

你的意思是编译器或运行时?

运行时足够智能,所以它会抛出InvalidCastException。然而编译器无法确定你的对象是什么类型,因为你装了你的int。

装箱和拆箱启用值类型 被视为对象。装箱 值类型将其打包在对象参考 类型的 实例中。

因此,由于它作为一个对象装箱,编译器不会抱怨它。

参见装箱和拆箱这里的更多信息:

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

3

退房this blog post通过埃里克利珀的血淋淋的细节。

它的要点是编译器会很慢(通过试验和错误,因为object可以是任何东西)哪种类型已被装箱以及它是否可以安全地投射。