You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何is not { }模式匹配可空值类型与引用类型时可空性表现不同?

关于C#中is not {}模式与可空类型的类型推断问题

先搞懂底层:可空值类型和可空引用类型根本不是一回事

C#里这俩可空是完全不同的实现:

  • int?这种可空值类型是Nullable<T>结构体,相当于给值类型套了个“有没有值”的标记,非null状态下必然有一个有效的int值。
  • Location?这种可空引用类型只是编译器的静态注解,运行时它还是普通的Location引用,空值就是普通的null引用,没有额外包装。

两种模式的本质差异

1. 类型模式(is not Location loc/is not int id)

你写is not 类型 变量的时候,是在做类型匹配检查:

  • 对int?来说,is not int id相当于“这个可空int不是null,并且能转成int”,所以id直接被推断成非空的int——毕竟只有非null的int?才能匹配int类型。
  • 对Location?来说,is not Location loc是“这个可空引用不是null,并且是Location类型”(本来就是),编译器会直接把loc推断成非空的Location——因为你明确指定了要匹配的类型,编译器就会去掉可空注解。

2. 空模式(is not {})

is not {}就是is not null的简写,它只做null检查,不涉及类型转换:

  • 对int?来说,非null就意味着有有效的int值,编译器可以安全地把id推断成int(自动解包)。
  • 对Location?来说,is not {}只告诉你这个引用不是null,但不会自动修改变量的可空注解——因为可空引用类型的注解是静态分析用的,空模式没说要把它转成非空类型,所以loc的类型还是Location?,只是编译器静态分析时知道它现在不为null(代码里可以安全用,不用加空判断)。

再看Roslyn文档的例子

文档里的int? x = 3; if (x is int v)是类型模式,编译器通过类型匹配自动解包了可空值类型,所以v是int——这和你第一个场景里is not int id的逻辑完全一致,都是类型模式触发的自动转换。而空模式不做类型转换,所以引用类型不会改可空注解。

内容的提问来源于stack exchange,提问作者exSnake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 12:10:36