【问题标题】:C# - Issues with boxing / unboxing / typecasting ints. I don't understandC# - 装箱/拆箱/类型转换整数的问题。我不明白
【发布时间】:2012-01-07 17:12:26
【问题描述】:

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

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' 的值。

这到底是怎么回事?

【问题讨论】:

  • Int16 实际上是一个short。所以我认为你可以替换'Int16 firstTest = Convert.ToInt16(0);' with 'Int16 firstTest = 0s;'

标签: c# c#-4.0 casting boxing unboxing


【解决方案1】:

拆箱检查确切的类型,如documentation 中所述。

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

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

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

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

同时引用文档:

为了在运行时成功拆箱值类型,项目被 unboxed 必须是对先前创建的对象的引用 通过装箱该值类型的实例。尝试拆箱 null 导致 NullReferenceException。试图取消对一个引用的装箱 不兼容的值类型会导致 InvalidCastException。

因此,要修复此错误,请确保类型匹配,然后再尝试拆箱:

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

【讨论】:

  • 或者使用正确的类型将其拆箱,然后转换为您想要的类型。 int thirdtest2 = (int)(short)thirdTest;
【解决方案2】:

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

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

在第二种情况下,您有一个装箱的 int,它正在分配回一个 int。这是一个简单的整数拆箱,也是有效的,所以它可以工作。

在第三种情况下,您有一个短的、装箱的,您试图将其拆箱成一个不是短的变量。这不是一个有效的操作:你不能一步完成。这也不是一个罕见的问题:例如,如果您使用的是包含 SMALLINT 列的 SqlDataReader,则不能这样做:

    int x = (int)rdr["SmallIntColumn"];

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

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

【讨论】:

    【解决方案3】:

    Int16short 的一种写法;那里没有装箱/拆箱,只是 16 位和 32 位整数之间的普通 CLR 转换。

    第二种情况下装箱和拆箱为同一类型,这是允许的:值类型int 被包裹在object 中,然后被拆箱。

    第三种情况尝试拆箱到一个不同的类型(int而不是short),这是不允许的。

    【讨论】:

      猜你喜欢
      • 2012-10-27
      • 1970-01-01
      • 2015-09-02
      • 2021-09-18
      • 1970-01-01
      • 2016-06-27
      • 2018-06-20
      • 1970-01-01
      相关资源
      最近更新 更多