首页 > 解决方案 > 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 之类的规则,这是我通过测试确认的行为。但这不是文档所说的;在我看来,拳击箱不见了。这个分析是正确的还是我遗漏了什么?

标签: c#

解决方案


在您的示例中,表达式E对应于您的变量o。它的(静态)类型是object,它的运行时类型是int

然后按照这个规则

如果 的类型E是引用类型,D则为实例引用的运行时类型E

is的动态类型D,因为规则前项中的“类型”指的是静态类型,在我们的例子中它确实是一个引用类型。Eint

运算符的定义is进一步指定

IfT是一个不可为空的值类型,如果DT是相同的类型,则结果为真。

在这种情况下,T对应于int(因为您正在测试o is int)。因此o is int是真的,因为DT都是int


推荐阅读