c# - C# 是运算符,拆箱的确切行为
问题描述
关于 is 运算符的C# 语言规范文档如下:
操作的结果
E is T
,其中 E 是表达式,T 是类型,是一个布尔值,指示 E 是否可以通过引用转换、装箱转换或拆箱转换成功地转换为 T 类型。[...]
[...] 让 D 表示 E 的动态类型,如下所示:
- 如果 E 的类型是引用类型,则 D 是 E 引用的实例的运行时类型。
- 如果 E 的类型是可空类型,则 D 是该可空类型的基础类型。
- 如果 E 的类型是不可为空的值类型,则 D 是 E 的类型。
操作的结果取决于 D 和 T,如下所示:[...继续目标类型]
然后文档继续对目标类型进行类似的区分。因为我只对表达式的类型感兴趣,所以我对那部分以及与这个问题不相关的空案例感兴趣。
当我有这样的事情时:
object s = "hey";
if (s is string) ...
这是第一个适用的情况。
当我有这样的事情时:
int? nullableInt = 10;
if (nullableInt is int) ...
这是适用的第二种情况:E是可为空的类型,而 int 是其基础类型。很没用。
但是当我有这样的东西时,那就是一个装在对象中的值,似乎缺少一条规则。
object o = (int)10;
if (o is int) ...
这里表达式的静态类型是object,即引用类型,而它的运行时类型是值类型。
这是类型测试的一个非常(也许是最)常见的场景。
由于表达式的静态类型是引用类型,因此它应该是第一种适用的情况。
但是当引用类型的“内容”是值类型时,它应该对装箱值应用 2 和 3 之类的规则,这是我通过测试确认的行为。但这不是文档所说的;在我看来,拳击箱不见了。这个分析是正确的还是我遗漏了什么?
解决方案
在您的示例中,表达式E
对应于您的变量o
。它的(静态)类型是object
,它的运行时类型是int
。
然后按照这个规则
如果 的类型
E
是引用类型,D
则为实例引用的运行时类型E
。
is的动态类型D
,因为规则前项中的“类型”指的是静态类型,在我们的例子中它确实是一个引用类型。E
int
运算符的定义is
进一步指定
If
T
是一个不可为空的值类型,如果D
和T
是相同的类型,则结果为真。
在这种情况下,T
对应于int
(因为您正在测试o is int
)。因此o is int
是真的,因为D
和T
都是int
。