C# - 装箱/拆箱/类型转换整数问题。我不明白

发布于 2024-12-25 13:51:04 字数 632 浏览 2 评论 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.
}

我在运行时收到的具体错误是 Specifiedcast is not valid.。如果我在 Visual Studio 中 QuickWatch (int)thirdTest,我会得到以下值: 无法将“thirdTest”拆箱为“int”

这到底是怎么回事?

I'm having a hard time understanding this. Consider the following example:

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

The specific error that I get at runtime is Specified cast is not valid. If I QuickWatch (int)thirdTest in Visual Studio, I get a value of Cannot unbox 'thirdTest' as a 'int'.

What the heck is going on here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

述情 2025-01-01 13:51:04

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

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

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

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

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

还引用文档中的内容:

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

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

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

Unboxing checks the exact type as explained in the documentation.

Unboxing is an explicit conversion from the type object to a value
type or from an interface type to a value type that implements the
interface. An unboxing operation consists of:

  • Checking the object instance to make sure that it is a boxed value of
    the given value type.

  • Copying the value from the instance into the value-type variable.

As you can see the first step is to check that the object instance matches the target type.

Also quote from the documentation:

For the unboxing of value types to succeed at run time, the item being
unboxed must be a reference to an object that was previously created
by boxing an instance of that value type. Attempting to unbox null
causes a NullReferenceException. Attempting to unbox a reference to an
incompatible value type causes an InvalidCastException.

So to fix this error make sure that the type matches before attempting to unbox:

object thirdTest = Convert.ToInt16(0);
short thirdtest2 = (short)thirdTest;  
墨离汐 2025-01-01 13:51:04

发生的事情正如它所说的那样。

在第一种情况下,您有一个简短的、未装箱的,然后将其显式转换为 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;

What's going on is exactly what it says.

In the first case, you have a short, unboxed, that you are then explicitly typecasting to an int. This is a valid conversion that the compiler knows how to do, so it works.

In the second case, you have an int, boxed, that are are assigning back to an int. This is a simple unboxing of an integer, which also valid, so it works.

In the third case, you have a short, boxed, that are you trying to unbox into a variable that is not a short. This isn't a valid operation: you can't do this in one step. This is not an uncommon problem, either: if you are using, for example, a SqlDataReader that contains a SMALLINT column, you cannot do:

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

Either of the following should work in your third example:

    object thirdTest = Convert.ToInt16(0);
    int thirdTest2 = Convert.ToInt32(thirdTest);
    int thirdTest3 = (int)(short)thirdTest;
回忆那么伤 2025-01-01 13:51:04

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

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

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

Int16 is a fancy way to write short; there is no boxing/unboxing going on there, just the plain CLR conversion between 16-bit and 32-bit integers.

The second case boxes and unboxes to the same type, which is allowed: value type int gets wrapped in an object, and then gets unwrapped.

The third case tries to unbox to a different type (int instead of short) which is not allowed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文