C#-装箱/拆箱/类型转换INT的问题。我不知道';我不明白

C#-装箱/拆箱/类型转换INT的问题。我不知道';我不明白,c#,c#-4.0,casting,boxing,unboxing,C#,C# 4.0,Casting,Boxing,Unboxing,我很难理解这一点。考虑下面的例子: protected void Page_Load(object sender, EventArgs e) { // No surprise that this works Int16 firstTest = Convert.ToInt16(0); int firstTest2 = (int)firstTest; // This also works object secondTest = 0; int seco

我很难理解这一点。考虑下面的例子:

protected void Page_Load(object sender, EventArgs e)
{
    // No surprise that this works
    Int16 firstTest = Convert.ToInt16(0);
    int firstTest2 = (int)firstTest;

    // This also works
    object secondTest = 0;
    int secondTest2 = (int)secondTest;

    // But this fails!
    object thirdTest = Convert.ToInt16(0);
    int thirdtest2 = (int)thirdTest;  // It blows up on this line.
}
我在运行时遇到的特定错误是
指定的强制转换无效。
如果我在Visual Studio中使用QuickWatch
(int)thirdTest
,我会得到
的值,无法将'thirdTest'取消装箱为'int'


这到底是怎么回事?

取消装箱将检查中解释的确切类型

取消装箱是从类型对象到值的显式转换 类型或从接口类型转换为实现 接口。取消装箱操作包括:

  • 检查对象实例以确保它是的装箱值 给定的值类型

  • 将值从实例复制到值类型变量中

如您所见,第一步是检查对象实例是否与目标类型匹配

同时引用文件中的内容:

要在运行时成功取消值类型的装箱,需要 “取消绑定”必须是对先前创建的对象的引用 通过装箱该值类型的实例。正在尝试取消装箱null 导致NullReferenceException。正在尝试取消对对象的引用的装箱 不兼容的值类型导致InvalidCastException

因此,要修复此错误,请在尝试取消装箱之前确保类型匹配:

object thirdTest = Convert.ToInt16(0);
short thirdtest2 = (short)thirdTest;  

所发生的事情正是它所说的

在第一种情况下,您有一个简短的、未装箱的,然后显式地将其类型转换为int。这是一个有效的转换,编译器知道如何进行,因此它可以工作

在第二种情况下,您有一个int,已装箱,正在重新分配给int。这是一个简单的整数解装箱,它也是有效的,因此可以工作

在第三种情况下,您有一个短的、已装箱的变量,您试图将其解装箱到一个非短的变量中。这不是有效的操作:不能一步完成。这也是一个常见的问题:例如,如果您使用的
SqlDataReader
包含
SMALLINT
列,则无法执行以下操作:

    int x = (int)rdr["SmallIntColumn"];
在您的第三个示例中,以下任一项都应适用:

    object thirdTest = Convert.ToInt16(0);
    int thirdTest2 = Convert.ToInt32(thirdTest);
    int thirdTest3 = (int)(short)thirdTest;

Int16
是编写
short
的奇特方式;这里没有装箱/拆箱,只有16位和32位整数之间的普通CLR转换

第二种情况是将框和解框设置为相同的类型,这是允许的:值类型
int
被包装在
对象中,然后被展开


第三种情况尝试取消装箱到不允许的其他类型(
int
,而不是
short
)。

Int16实际上是一个short。因此,我认为可以将“Int16 firstTest=Convert.ToInt16(0);”使用“Int16 firstTest=0s;”或者使用正确的类型将其取消装箱,然后转换为所需的类型<代码>整数第三测试2=(整数)(短)第三测试