C# - 装箱/拆箱/类型转换的问题.我不明白

Jer*_*ins 8 c# boxing unboxing casting c#-4.0

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

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

我在运行时获得的具体错误是在Visual Studio中的Specified cast is not valid. If I QuickWatch (int)thirdTest,我得到的值为Cannot unbox 'thirdTest' as a 'int'.

到底发生了什么事?

Dar*_*rov 12

拆箱检查确切类型,如文档中所述.

拆箱是从类型对象到值类型或从接口类型到实现接口的值类型的显式转换.拆箱操作包括:

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

  • 将实例中的值复制到value-type变量中.

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

同样引用文档:

要使值类型的取消装箱在运行时成功,要取消装箱的项必须是对先前通过装箱该值类型的实例创建的对象的引用.尝试取消设置null会导致NullReferenceException.尝试取消对不兼容的值类型的引用取消导致InvalidCastException.

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

object thirdTest = Convert.ToInt16(0);
short thirdtest2 = (short)thirdTest;  
Run Code Online (Sandbox Code Playgroud)

  • 或者使用正确的类型将其拆箱,然后转换为您想要的类型.`int thirdtest2 =(int)(short)thirdTest;` (2认同)

Mic*_*eld 9

究竟是怎么回事.

在第一种情况下,您有一个简短的未装箱的,然后您可以明确地将其转换为int.这是编译器知道如何操作的有效转换,因此它可以工作.

在第二种情况下,你有一个int,boxed,它们正在分配给一个int.这是一个整数的简单拆箱,它也有效,所以它可以工作.

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

    int x = (int)rdr["SmallIntColumn"];
Run Code Online (Sandbox Code Playgroud)

以下任何一个都应该适用于您的第三个示例:

    object thirdTest = Convert.ToInt16(0);
    int thirdTest2 = Convert.ToInt32(thirdTest);
    int thirdTest3 = (int)(short)thirdTest;
Run Code Online (Sandbox Code Playgroud)