奇怪的铸造行为.无法将object(int)强制转换为long

Bas*_*dov 44 .net c# clr

我有以下代码:

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?
Run Code Online (Sandbox Code Playgroud)

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

如果我使用vardynamic代替object,它的工作原理.

有什么想法吗?

svi*_*ick 53

从中转换intlong被解释为两种类型之间的转换.

从中object转换int为解释为装箱的装箱int.

它的语法相同,但它表示两种不同的东西.

在工作案例中(intlong,object(盒装int)→ int),编译器确切地知道要生成什么代码.如果盒装intlong工作,编译器必须以某种方式确定要使用哪个转换,但它没有足够的信息来执行它.

另请参阅Eric Lippert的这篇博客文章.

  • @Bashir Magomedov:Eric Lippert的博客文章相当不错,强烈建议你阅读它. (2认同)

Abe*_*bel 7

object持有型int.但它被认为是一个对象(它是一个盒装的int),盒装值类型通常只能转换为它的底层类型(盒装的类型).

要将其转换为其他类型,首先必须将其强制转换为其基础类型.这有效:

long longNumber2 = (long) (int) intNumber2;
Run Code Online (Sandbox Code Playgroud)

有效的原因var是编译器在编译时推断出类型.这意味着,当您使用时var,intNumber2(如果您使用typeof)的类型将是int.而当你使用时object,类型将是object.

使用dynamic是一个完全不同的过程,无法与之进行比较var.这里,转换/转换使用反射和DLR库在运行时进行.它将动态查找基础类型,发现它具有转换运算符并使用它.