奇怪的铸造行为。 无法将对象(int)强制转换为long

我有以下代码:

int intNumber1 = 100; object intNumber2 = 100; bool areNumberOfTheSameType = intNumber1.GetType() == intNumber2.GetType(); // TRUE bool areEqual = intNumber1.Equals(intNumber2); // TRUE long longNumber1 = (long) intNumber1; // OK long longNumber2 = (long) intNumber2; // InvalidCastException. Why? 

为什么第二次演员不工作? 我意识到这可能是因为对象没有明确的转换,但如果我们在运行时查看它的types,它是System.Int32

如果我使用vardynamic而不是object ,它的工作原理。

有什么想法吗?

intlong转换被解释为两种types之间的转换。

objectint被解释为取消装箱的int

这是相同的语法,但它说了两个不同的东西。

在工作案例( intlongobject (boxed int )→ int )中,编译器确切知道要生成的代码。 如果boxed intlong是工作,编译器将不得不想出哪个转换来使用,但它没有足够的信息去做。

另见Eric Lippert的博客文章 。

object包含一个inttypes。 但是它被认为是一个对象(这是一个盒装的int)和一个盒装的值types通常只能被转换为它的底层types(被装箱的types)。

要将其转换为其他types,首先必须将其转换为其基础types。 这工作:

 long longNumber2 = (long) (int) intNumber2; 

var工作的原因是编译器在编译时推断types。 这意味着,当你使用varintNumber2的types(如果你使用typeof )将是int 。 而当你使用object ,types将是object

使用dynamic是一个完全不同的过程,不能与var进行比较。 在这里,转换/转换在运行时发生,使用reflection和DLR库。 它会dynamic地find底层的types,发现它有一个转换操作符并使用它。

(小心:猜测)

Int32有一个转换运算符到Int64 ,当你第一次转换的时候被调用。 Object没有,所以你的第二个Int64尝试将对象转换为不是超types的另一个types( Int64不inheritanceInt32 )。

为什么它与var工作的原因是显而易见的 – 编译器只是在这种情况下保存你inputint 。 在dynamic的情况下,运行时会执行所有必要的检查,而通常情况下编译器只会插入转换或调用转换运算符。

由于是两种不同types的演员(一个转换,另一个拆箱),所以它不起作用已经在这里回答了。 什么可能是一个有用的补充, Convert.ToInt64()将任何内置的types,可以转换为长,或实现IConvertible.ToInt64()类的typesIConvertible.ToInt64()为长。 换句话说,如果你希望能够将一个包含一个整数(无论大小)的对象转换为long, Convert.ToInt64()就是要走的路。 这是更昂贵的,但是你要做的更昂贵的铸造,差异是可以忽略的(只要足够大的浪费,如果你知道对象必须是盒装长)。

您需要将相同types的盒子取消装箱。

 object intNumber2 = 100L; // or value in the long type range // object intNumber2 = 9223372036854775806; long result = (long)intNumber2;