我找不到以下问题的答案:
object o = 10; // Box
int i = (int)o; // Unbox
很清楚,但以下不清楚
bool isInt = o is int; // Is the unbox here or not?
不,这不是拆箱——它只是检查类型是否正确。不要忘记确实有一个对象,有一个类型。无论该值是否为装箱值类型值,检查该类型基本上是相同的操作。(对于值类型或任何密封类型,可能有一些可行的优化,因为没有要考虑的继承,但从根本上说,它仍在检查对象头的“类型”部分。)
一种检查方法是编译代码并使用 ILASM 查看 IL:
// object o = 10
IL_0000: ldc.i4.s 10
IL_0002: box [mscorlib]System.Int32
IL_0007: stloc.0
// int i = (int) o;
IL_0008: ldloc.0
IL_0009: unbox.any [mscorlib]System.Int32
IL_000e: stloc.1
// bool isInt = o is int
IL_000f: ldloc.0
IL_0010: isinst [mscorlib]System.Int32
所以它使用isinst
- 不需要拆箱。
它不仅不需要拆箱,从逻辑上讲,它也不需要。
拆箱可以成功也可以失败,这取决于对象是否真的包含我们要尝试拆箱的类型的值。
因此,拆箱需要检查对象是否属于该特定类型。
因此,如果测试类型需要拆箱,那么由于拆箱需要测试类型,我们将无法拆箱,直到我们第一次拆箱......
因此测试一个类型不需要拆箱。
从 C# 7 开始,is
关键字获得了一个新的用例,在模式匹配中作为类型模式。在这种情况下,确实会发生拆箱,例如:
object o = 10;
if (o is int i) {
// i is the unboxed value.
}
显然,这与原始帖子的情况不同,原始帖子中的值纯粹是被测试的,因为当is
用作模式时,您实际上是在分配值。因此在这种情况下需要拆箱。
需要明确的是 - 原始o is int
案例没有任何改变 - 根据旧答案,那里不会发生拆箱。is
关键字刚刚获得了新的作用。