CLR如何知道盒装对象的类型?

当值类型被加框时,它被放置在无类型的引用对象中。 那么是什么导致了无效的强制转换exception?

long l = 1; object obj = (object)l; double d = (double)obj; 

不,它不是放在一个无类型的对象中。 对于每种值类型,CLR中都有一个盒装引用类型。 所以你有类似的东西

 public class BoxedInt32 // Not the actual name { private readonly int value; public BoxedInt32(int value) { this.value = value; } } 

虽然它是在C ++ / CLI中,但在C#中无法直接访问该盒装类型。 显然知道原始类型。 所以在C#中你必须有一个编译时类型的变量object ,但这并不意味着它是对象的实际类型。

有关更多详细信息,请参阅ECMA CLI规范或CLR通过C# 。

Jon Skeet的答案涵盖了原因; 至于如何绕过它,这是你必须做的:

 long l = 1; object obj = (object)l; double d = (double)(long)obj; 

双重演员的原因是这样的; 当.NET取消变量变量时,它只知道如何将它拆箱到它所装箱的类型中(在你的例子中long )。一旦你取消装箱它并且你有一个合适的long原语,你就可以把它变成double或者任何其他类型的铸造从long