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

咨询C#中notnull约束与可空类型结合出现异常行为的原因

关于notnull约束允许int?和string?实例化的原因

你引用的《Programming C# - 10.0》里对notnull约束的描述是准确的,但这个约束的行为和nullable上下文设置、C#里两种“可空类型”的本质差异直接相关,下面分点解释你的疑问:

1. 可空值类型int?完全符合notnull约束

int?是Nullable<int>的语法糖,它本身是一个值类型结构体,而notnull约束明确允许所有值类型(包括可空值类型)。这里的关键是:约束检查的是类型本身,而不是该类型的实例能否表示null状态。

你看到输出里System.Nullable1[System.Int32]的默认值是Null,这只是Nullable的默认状态(HasValue=false),但这个类型本身是值类型,完全满足notnull`约束的要求。

2. string?能通过编译是因为nullable上下文未启用

可空引用类型(比如string?)是C# 8.0引入的编译时注解,在运行时string?和string是完全相同的类型——这就是你输出里看到Type of T is System.String的原因。

notnull约束对可空引用类型的限制只在启用严格nullable上下文时生效:

  • 如果你的项目没有设置<Nullable>enable</Nullable>(默认是<Nullable>warning</Nullable>或关闭状态),编译器不会强制执行notnull约束对可空引用类型的检查,会自动将string?当作string处理,所以代码能正常编译运行。
  • 一旦启用严格nullable上下文,编译器会直接抛出错误,禁止用string?实例化带有notnull约束的泛型类。

3. notnull约束的双重作用逻辑

notnull约束的检查分为两个层面:

  • 编译时:仅在启用nullable上下文时生效,会拦截可空引用类型传入,但允许值类型(包括可空值类型)。
  • 运行时:对引用类型无任何检查(因为运行时没有可空引用类型的概念);对值类型,由于值类型本身不可能是null引用(可空值类型的null是结构体的状态),所以也不会触发运行时错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:12:45