C# 9.0 新特性预览 - 空参数校验

前言

随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们。

目录

[C# 9.0 新特性预览 - 类型推导的 new]
[C# 9.0 新特性预览 - 空参数校验]
[C# 9.0 新特性预览 - Lambda 中的弃元]
[C# 9.0 新特性预览 - Record 类型]
[C# 9.0 新特性预览 - 模式匹配的改善]
[C# 9.0 新特性预览 - 其他小的变化]

简便的空参数校验 (Simplified Null Argument Checking)

目的

这个特性主要是为了更简便的检查方法的参数是否为 null 并抛出 ArgumentNullExceptiony 异常。

语法

语法很简单,在参数名后加个叹号即可:

void M(string name!) {
...
}

以上代码会被翻译为:

void M(string name) {
if (name is null) {
throw new ArgumentNullException(nameof(name));
}
...
}

想必有些同学已经从上面代码看出来了,这个生成的空校验,只是校验参数是否为 null,这也就意味着它无法在值类型上使用,以下代码将报错:

// Error: 无法在值类型参数上使用!操作符
void G<T>(T arg!) where T : struct { }

当然,可空的值类型是可以的,但是编译器会提示一条警告,提示你在可空类型上进行了空检查:

// Warning: 将显式null检查与可为null的类型结合使用
void M(int? x!) {
}

类似的,在参数拥有默认值的情况下,也会提示警告

// Warning: 参数 'x' 进行了空检查但是它默认为空
void M(string x! = null) {
}

构造方法的场景

在构造方法的场景下,空参数校验将发生在任何其他代码的前面,包括:

  • 对其他构造方法的链式调用,即 this() 或 base()
  • 在构造方法内的隐式字段初始化

举个例子:

class C {
string field = GetString();
C(string name!): this(name) {
...
}
}

以上代码会大致翻译为以下伪代码:

class C {
C(string name)
if (name is null) {
throw new ArgumentNullException(nameof(name));
}
field = GetString();
:this(name);
...
}

Lambda 的场景

这个特性在 lambda 中也可以使用

void G() {
Func<string, string> s = x! => x;
}

不可以使用的场景

这个特性只能用于有方法体的方法中,也就意味着它不能用于抽象方法、接口、委托和部分方法。
以下代码编译器会报错:

interface C
{
public int M(string x!);// ERROR
}

不能用于属性。因为属性 setter 中的 value 是隐式的,不会出现在参数列表中,所以此特性不适用于属性。

string FirstName! { get; set; } // ERROR

不能用于 out / ref / in 的参数

public void M(out string x!) {} // ERROR

参考

[Proposal: Simplified Null Argument Checking]
[Unit test: NullCheckedParameterTests.cs]
[LDM-2019-07-10.md]

C# 9.0 新特性预览 - 空参数校验的更多相关文章

  1. C# 9.0 新特性预览 - 类型推导的 new

    C# 9.0 新特性预览 - 类型推导的 new 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大 ...

  2. C# 9.0 新特性预览 - 顶级语句

    C# 9.0 新特性预览 - 顶级语句 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们 ...

  3. C# 9.0 新特性预览 - init-only 属性

    C# 9.0 新特性预览 - init-only 属性 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章 ...

  4. Vue.js 3.0 新特性预览

    总结起来,Vue 3 以下方面值得我们期待 : 更快 更小 更易于维护 更多的原生支持 更易于开发使用 完整的PPT:docs.google.com/presentatio… Evan 和 Vue 团 ...

  5. Windows Phone 8.1SDK新特性预览

    前言    Windows Phone 8.1的预览版将在近期推送,WP 8.1的SDK也已经进入到RC阶段,可以从这里安装.本次更新的SDK被直接集成到了VS2013Update2里面,不再是单独的 ...

  6. avalon1.3的新特性预览

    avalon1.2的性能优化风暴很快就告一段落,入职也快一个月了,许多乱七八糟的事也少了下来,估计未来一个月会有许多好东呈现给大家. 首先是一个性能检测工具.由于MVVM是将原本由人脑干的事,转到各种 ...

  7. Office 2016 正式发布——新特性预览

    今天微软又发生了一件大事!Windows Office 2016正式发布,这标志着Windows Office 又达到了一个新的里程碑! 全新的Office 发布为Office 365 用户带来了新的 ...

  8. CSS3_新特性预览

    一.强大的CSS选择器 以前我们通常用class. ID 或 tagname 来选择HTML元素,CSS3的选择器强大的难以置信.  它们可以减少在标签中的class和ID的数量更方便的维护样式表.更 ...

  9. C# 4.0 新特性dynamic、可选参数、命名参数等

    1.dynamic ExpandoObject熟悉js的朋友都知道js可以这么写 :   1 var t = new Object(); 2 t.Abc = ‘something’; 3 t.Valu ...

随机推荐

  1. Supermarket POJ - 1456(贪心)

    题目大意:n个物品,每个物品有一定的保质期d和一定的利润p,一天只能出售一个物品,问最大利润是多少? 题解:这是一个贪心的题目,有两种做法. 1 首先排序,从大到小排,然后每个物品,按保质期从后往前找 ...

  2. 解决SpringMVC的乱码问题:CharacterEncodingFilter

    在使用 SpringMVC 框架的过程中,如果前台有包含中文的请求,或者后台有包含中文的响应,有可能会出现乱码的情况.在以前的 Servlet 中,我们使用 request.setCharacterE ...

  3. c++类初始化列表初探

    目录 1 初始化和赋值 1.1 结论 2 构造函数初始化列表 2.1 结论 3 必须使用初始化列表的情况 3.1 结论 4 成员初始化顺序 5 参考资料 1 初始化和赋值 初始化:创建一个对象并赋予一 ...

  4. sws_接口自动化_demo

    登录接口获取token: import requests import json def get_token(username, password): host = "https://sws ...

  5. phpcms 后台分页

    php 代码public function init() { $where='';//条件 $page = $_GET['page'] ? intval($_GET['page']) : '1'; $ ...

  6. 2019-2020-1 20199326《Linux内核原理与分析》第六周作业

    本周学习了庖丁解牛Linux内核分析第五章:系统调用的三层机制(下),是上一章的延续 实验内容:使用gdb跟踪分析一个系统调用内核函数 上周实验我选择的getpid这个系统系统调用,这次准备使用gdb ...

  7. 文件包含漏洞(pikachu)

    文件包含漏洞 在web后台开发中,程序员往往为了提高效率以及让代码看起来更加简洁,会使用'包含'函数功能,比如把一系列功能函数都写进function.php中,之后当某个文件需要调用的时候,就直接在文 ...

  8. python学习10字典

    '''''''''字典(Dict)是python语言的一个最大的特征1.定义:是可变的无序集合,以键值对为基本元素,可以存储各种数据类型2.表示:{} 列表:[] 元组 () 字符串 ‘’ “” ‘‘ ...

  9. (转)SQLite数据库的加密

    1.创建空的SQLite数据库. //数据库名的后缀你可以直接指定,甚至没有后缀都可以 //方法一:创建一个空sqlite数据库,用IO的方式 FileStream fs = File.Create( ...

  10. 【Linux常见命令】route命令

    route - show / manipulate the IP routing table route命令用于显示和操作IP路由表. route命令用来显示并设置Linux内核中的网络路由表,rou ...