介绍
C# 11 将引入一个新的运算符! 简化代码中参数的空检查。 该版本已经支持此语法。 如果您有兴趣,不妨尝试一下。 我们来看看如何使用它。
如果想在本地代码中编译测试,需要安装.NET 7 1 SDK,下载地址:然后在本地创建一个控制台应用程序,可以使用命令new来创建,手动修改项目文件,配置C#语言版本为,添加如下:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>ExeOutputType>
<Targetframework>net7.0Targetframework>
<ImplicitUsings>enableImplicitUsings>
<Nullable>enableNullable>
+ <LangVersion>previewLangVersion>
PropertyGroup>
Project>
!! 是一个new运算符,将其添加到参数后编译器会自动生成一段空检查代码
嘭嘭
我们来尝试一下,测试代码如下:
Hello("World");
try
{
Hello(null!);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
void Hello(string name!!)
{
Console.WriteLine($"Hello, {name}!");
}
运行run执行代码,可以看到类似如下的输出:
可以看到,当传递null时,会抛出n异常,说明确实做了null检查
该运算符不仅适用于方法参数,还适用于委托参数、索引器等。
什么是
从上面的输出中,我们可以看到存在空检查。 它实际上是什么样子的? 我们可以反编译代码,看看实际生成的代码是什么样的。 反编译结果如下:
类型和Main方法由编译器自动生成,是C#9引入的顶级语句(Top-Level)
可以看到我们代码中的Hello方法不见了,多了一个编译器生成的方法。 是我们原来方法的变形,只增加了一行代码。
<PrivateImplementationDetails>.ThrowIfNull(name, "name");
我们再看一下实现,如下:
可以看到这里实现了null检查。 如果参数为null,则会抛出n异常。 相信大家都知道它是如何实现的。 那么就有一个问题需要思考。 这里我们使用一个方法。 如果有两个这样的方法会是什么样子?
这个类会生成两个吗?我们来试试吧,我们把这个方法复制一下,改个名字,反编译一下
void Hello1(string name!!) => Console.WriteLine($"Hello, {name}!");
反编译结果如下:
可以看到实际上调用的是同一个方法,
这个类型只生成一次,那么如果这两个方法在两个项目中怎么办? 你可以自己尝试一下~~
更多的
使用该运算符时,有一些注意事项。 如果启用可为空引用类型并将参数声明为可为空引用类型,编译器会产生警告,因为它实际上不应该为 null,为 null 会抛出异常,因此编译器会发出警告,示例为如下:
// warning CS8995: Nullable type 'string?' is null-checked and will throw if null.// void Hello2(string? name!!) => Console.WriteLine($"Hello, {name}!");
值类型不能使用该运算符,因为值类型不会为null,编译器会直接报错,但可为null的值类型是可以的,例如:
// error CS8992: Parameter 'int' is a non-nullable value type and cannot be null-checked.// void Hello3(int name!!) => Console.WriteLine($"Hello, {name}!");
另外,out参数不能使用该运算符,如:
// error CS8994: 'out' parameter 'name' cannot be null-checked.// void Hello4(out string name!!) => name = "World";
想要尝试的朋友可以安装.NET 7 1来体验。 如果他们不想安装,也可以通过在线网站体验编译器的新功能
.NET中的代码已经使用了这个new运算符来简化参数的null检查,可以参考:
- 结束符 -