C#-装箱/取消装箱/类型转换int的问题.我没有';我不明白

本文关键字:明白 问题 取消装箱 装箱 类型转换 int C#- | 更新日期: 2023-09-27 18:19:52

我很难理解这一点。考虑以下示例:

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.
}

我在运行时得到的特定错误是Specified cast is not valid.如果我在Visual Studio中快速观察(int)thirdTest,我得到的值是Cannot unbox 'thirdTest' as a 'int'

这到底是怎么回事?

C#-装箱/取消装箱/类型转换int的问题.我没有';我不明白

Unboxing检查文档中解释的确切类型。

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

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

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

正如您所看到的,第一步是检查对象实例是否与目标类型匹配。

同时引用文件:

为了在运行时成功取消值类型的装箱unboxed必须是对以前创建的对象的引用通过装箱该值类型的实例。正在尝试取消框null导致NullReferenceException。正在尝试取消框对的引用不兼容的值类型会导致InvalidCastException。

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

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

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

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

在第二种情况下,您有一个带框的int,它们正在向一个int赋值。这是对一个整数的简单拆箱,也是有效的,所以它可以工作。

在第三种情况下,您有一个short,boxed,也就是说您试图将其取消装箱到一个不是short的变量中。这不是一个有效的操作:不能一步到位。这也不是一个常见的问题:例如,如果您使用的是包含SMALLINT列的SqlDataReader,则不能执行以下操作:

    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被封装在object中,然后被展开。

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