[英]C# - Issues with boxing / unboxing / typecasting ints. I don't understand
我很难理解这一点。 考虑以下示例:
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 中使用 QuickWatch (int)thirdTest
,我会得到一个值Cannot unbox 'thirdTest' as a 'int'
。
这到底是怎么回事?
拆箱检查文档中解释的确切类型。
拆箱是从类型对象到值类型或从接口类型到实现接口的值类型的显式转换。 拆箱操作包括:
检查对象实例以确保它是给定值类型的装箱值。
将值从实例复制到值类型变量中。
如您所见,第一步是检查对象实例是否与目标类型匹配。
还引用了文档:
为了在运行时成功取消装箱值类型,被取消装箱的项必须是对先前通过装箱该值类型的实例创建的对象的引用。 尝试取消装箱 null 会导致 NullReferenceException。 尝试取消装箱对不兼容值类型的引用会导致 InvalidCastException。
因此,要修复此错误,请在尝试取消装箱之前确保类型匹配:
object thirdTest = Convert.ToInt16(0);
short thirdtest2 = (short)thirdTest;
正在发生的事情正是它所说的。
在第一种情况下,您有一个简短的、未装箱的,然后您将其显式转换为 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;
Int16
是一种写short
的奇特方式; 那里没有装箱/拆箱,只有 16 位和 32 位整数之间的普通 CLR 转换。
第二种情况装箱和拆箱为相同的类型,这是允许的:值类型int
被包裹在一个object
,然后被解开。
第三种情况尝试拆箱为不允许的不同类型( int
而不是short
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.