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

fea*_*net 14 c# clr boxing type-conversion

当值类型被装箱时,它被放置在无类型的引用对象内.那么是什么导致无效的强制转换异常?

long l = 1;
object obj = (object)l;
double d = (double)obj;
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 17

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

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

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

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


Ada*_*ras 6

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

long l = 1;
object obj = (object)l;
double d = (double)(long)obj;
Run Code Online (Sandbox Code Playgroud)

双重演员的原因是这样的; 当.NET取消变量变量时,它只知道如何将它打包成它所装箱的类型(long在你的例子中).一旦你取消装箱它并且你有一个正确的long原语,你可以将它转换为double或任何其他类型来自long.