Liam W
封面

C# 11 移除了一个新特性

作者
王亮·发表于 2 年前

在先前的 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、社交媒体、会议听众等)。反对的观点归纳一下,主要有如下两种:

  1. 引入 !! 语法的同时也牺牲了可读性。在大多数语言中单个 ! 符号表示取反,数学中表示阶乘,而用 !! 表示“不能为空”就显得有些奇怪。与其引入 !!,不如引入一个新的 notnull 关键字。
  2. 不管是引入 !! 还是 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/