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'
。
这到底是怎么回事?
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
)。