在先前的 C# 11 预览版本中,C# 11 引入了一个新特性,允许在参数名称的末尾加上 !!
来简化空值检查(null-checking)。
比如下面这个方法使用传统的方式进行参数空值检查:
public static void M(string s)
{
if (s is null)
{
throw new ArgumentNullException(nameof(s));
}
// Body of the method
}
使用 !!
语法可以简写为:
public static void M(string s!!)
{
// Body of the method
}
此简写和上面的 if (param is null) throw new ArgumentNullException(...)
是等效的。
但此特性的预览版出来后,引起了社区的很多争论和反馈(来自于 GitHub 评论、MVP、社交媒体、会议听众等)。反对的观点归纳一下,主要有如下两种:
- 引入
!!
语法的同时也牺牲了可读性。在大多数语言中单个!
符号表示取反,数学中表示阶乘,而用!!
表示“不能为空”就显得有些奇怪。与其引入!!
,不如引入一个新的notnull
关键字。 - 不管是引入
!!
还是notnull
作为空值检查,都会与 NRT (Nullable Reference Types) 产生冲突,因为在 NRT 中本身就可以添加严格的空值检查。
微软 C# 团队表示感谢所有的反馈,社区的反馈使团队的洞察更广泛,将重新考虑是否在 C# 11 中引入这个新特性。但由于团队没有足够的信心认为这个特性是 C# 正确的功能设计,因此决定将其从 C# 11 中删除,在将来的版本中可能还会继续探讨这个话题,引入更好的设计。
虽然移除了 !!
特性,但有好几种有效的方式可以用一行代码来进行空值检查。如果你使用的是 .NET 6,建议使用 ArgumentNullException.ThrowIfNull
方法:
public static void M(string myString)
{
ArgumentNullException.ThrowIfNull(myString);
// method
}
使用 ThrowIfNull
方法的好处之一是它使用 CallerArgumentExpression
来自动在异常消息中包含参数名称:
System.ArgumentNullException: 'Value cannot be null. (Parameter 'myString')'
关于移除 !!
特性的官方博文:
https://devblogs.microsoft.com/dotnet/csharp-11-preview-updates/