PAYATHON 2026

C# 参数名后的 !! 是什么,为什么会出现在 .NET Runtime 源码中?

数据小陈

参数名后的 !! 是 C# 11 早期预览中的参数空值检查语法(parameter null-checking),编译器会据此自动插入运行时空值检查。该功能后来从 C# 11 中撤回,没有随正式版发布。因此,使用不支持这一实验语法的编译器时,string value!! 会报语法错误。官方撤回说明

value!! 原本表示什么?

对于问题中的普通方法,原设计是在执行方法体之前检查 value,如果它为 null,就抛出 ArgumentNullException。对应的显式检查为:

if (value is null)
{
    throw new ArgumentNullException(nameof(value));
}

这样,参数校验会在 value.Length 执行前完成。!! 只检查 null;如果参数是空字符串,代码仍会进入方法体,并由原有的 value.Length == 0 分支处理。早期预览说明

为什么官方 runtime 源码里会出现它?

.NET Runtime 曾参与这项语言功能的内部试用。官方当时介绍过 runtime 中使用该语法的改动,因此在相关历史提交中可能看到 !!。官方试用记录

这里没有提供具体文件、提交或构建日志,无法确认所展示代码实际使用了哪套编译器。如果该提交确实编译成功,一个合理的解释是其构建环境使用了支持这项实验功能的编译器。

不能仅凭这段代码推断当前 runtime 仍依赖保留该功能的定制 Roslyn。公开工具链也曾支持过它:官方在 Visual Studio 17.1 和 .NET SDK 6.0.200 中提供了该功能的早期预览,并要求启用 LangVersion=preview。当时的工具链说明

本地项目应该怎样修改?

删除参数声明中的 !!,并在方法开头显式校验参数。如果只删除符号,就会丢失原本预期的参数检查。

如果目标框架为 .NET 6 或更高版本,可以使用:

ArgumentNullException.ThrowIfNull(value);

这是官方撤回该语法时给出的替代方案。如果目标框架没有提供此 API,可以使用前面的 if (value is null) 写法。官方替代建议

如果需要复现历史源码构建,应先确认源码提交,再检查该提交的 SDK、编译器依赖和构建说明。LangVersion=preview 只启用所用编译器实际支持的预览功能,不能恢复已经移除的实现。

它与 value! 有什么区别?

表达式中的 value! 使用 null-forgiving operator,只影响编译器的空值分析,不执行运行时检查。即使 value 实际为 null,添加 ! 也不会使它变成非空值,不能替代参数校验。Microsoft Learn:null-forgiving operator

备注:内容仅供参考。