前言

在前面的文章中(《可空引用类型》),我们介绍过编译器会帮我们检查空引用,但是仅仅是警告。最好的方式还是在运行时用卫语句进行检查:

private void Test(WeatherForecast weatherForecast)
{if (weatherForecast == null){ throw new ArgumentNullException(nameof(weatherForecast));}
}

在.NET 6中,在ArgumentNullException类中添加了一个名为ThrowIfNull的新静态方法,它允许我们快速检查和抛出 ArgumentNullExceptions:

有意思的是,异常信息自动带出了参数名称,这样可以有效避免使用nameof用错参数。

那这是怎么做到的呢?

原理探究

查看ThrowIfNull的定义,可以看到还有一个默认参数,使用了CallerArgumentExpression属性声明:

public static void ThrowIfNull([NotNull] object? argument, [CallerArgumentExpression("argument")] string? paramName = null)

在编译时,编译器会把上面的代码编译成如下形式,传入了参数名:

ArgumentNullException.ThrowIfNull(weatherForecast, "weatherForecast");

原理利用

很可惜,.NET 6没有提供更多类似ThrowIfNull的帮助方法,但是我们可以利用CallerArgumentExpression实现自己的帮助类来简化卫语句。

比如:

public class ArgumentExceptionHelper {public static void ThrowIfNullOrEmpty(string? argument, [CallerArgumentExpression("argument")] string? paramName = null){if(string.IsNullOrEmpty( argument))throw new ArgumentNullException(paramName);}public static void ThrowIfOutOfRange(bool argument, [CallerArgumentExpression("argument")] string? paramName = null){if (argument)throw new ArgumentOutOfRangeException(paramName);}
}//使用
ArgumentExceptionHelper.ThrowIfNullOrEmpty(name);ArgumentExceptionHelper.ThrowIfOutOfRange(age <= 0);

最为奇妙的是,CallerArgumentExpression的功能是表示一个参数将传递给另一个参数的表达式作为字符串捕获。,错误提示的不是参数名称,而是实际传入的表达式,因此更清晰。

例如下面的错误提示Age<=0:

结论

在.NET 6之前,.NET中已有三个[Caller*]属性可用:

  • [CallerMemberName]

  • [CallerFilePath]

  • [CallerLineNumber]

详细介绍请参看:https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callermembernameattribute

利用这些属性,可以让编译器“神奇地”填充它们,帮助我们轻松获取调用者信息。

如果你觉得这篇文章对你有所启发,请帮忙点个或者在看

.NET 6新特性试用 | ArgumentNullException卫语句相关推荐

  1. .NET 6新特性试用 | 总结:我最喜欢的5个特性

    前言 不知不觉,<.NET 6新特性试用>系列文章已经写了20多篇,而今天终于要告一段落了. 如果你还没有看过,详细文章列表在这里: .NET 6新特性试用系列 在这么多特性中,我最喜欢如 ...

  2. 5.0 新特性试用体验之 Clustered Index

    作者:hzc989 原文来源: https://tidb.net/blog/69dd056c [是否原创]是 [首发渠道]TiDB 社区 [目录] 一.引言 二.基础前情回顾 三.era withou ...

  3. .NET 6新特性试用 | 可空引用类型

    前言 在查看<隐式using指令>功能时,我们在csproj中发现这样一个属性: 那么,Nullable到底是干嘛的? 可为空上下文 严格来说,这不是新特性,而是C# 8.0引入的特性之一 ...

  4. mysql 8.0基于事务ddl_MySQL8.0新特性——支持原子DDL语句

    MySQL 8.0开始支持原子数据定义语言(DDL)语句.此功能称为原子DDL.原子DDL语句将与DDL操作关联的数据字典更新,存储引擎操作和二进制日志写入组合到单个原子事务中.即使服务器在操作期间暂 ...

  5. .NET 6新特性试用 | PeriodicTimer

    前言 在.NET中,已经存在了5个Timer类: System.Threading.Timer System.Timers.Timer System.Web.UI.Timer System.Windo ...

  6. .NET 6新特性试用 | 可写JSON DOM API

    前言 我们常用JSON的方式,是将类对象序列化/反序列化: var user = new User { Name = "My IO" }; var json = JsonSeria ...

  7. .NET 6新特性试用 | 模式匹配之Extended Property Patterns

    前言 模式匹配是一种测试表达式以确定其是否具有某些特征的技术. 例如, 下面的Employee类和Manager类: public class Employee {public int Id { ge ...

  8. .NET 6新特性试用 | SDK工作负载

    前言 为了应对.NET SDK能够支持的程序集项目(例如iOS.Android.WASM)的不断增长,从.NET 6开始,允许用户仅安装必要的SDK(例如ASP.NET Core),而不是一次性安装& ...

  9. .NET 6新特性试用 | LINQ功能改进

    前言 .NET6为LINQ添加了多个新API,在本文中,我们将始终使用User类逐一演示这些添加到LINQ中的内容: public class User {public string Name { g ...

最新文章

  1. 主席树 + 树上倍增 ---- codeforces 587C[树上倍增或者主席树]
  2. JDBC:使用连接池管理连接
  3. 教师课堂教学必备的100个妙招,总有一个适合你!
  4. 技术剖析 | Axonius为什么能获得 2019 RSAC创新大奖
  5. python培训中心-深圳Python培训
  6. 无法安装ie8,因为其他程序或更新正在等待重启您的计算机,ie8 因为其他程序或更新正在等待重新启...
  7. python用电度数设计_在Python中动态模拟时绘制电压大小
  8. 转发:linux修改光盘作为源
  9. Cisco 3750文件系统学习总结
  10. .Net Core 学习笔记1——包、元包、框架
  11. 浏览器能上网,qq,百度云不能上
  12. Modular Arithmetic
  13. 基于PPGiPPG的心率检测原理
  14. 拒绝男程序员?程序员就活该接盘?
  15. Electron:WARNING Too many active WebGL contexts. Oldest context will be lost.
  16. 联想开机启动项按哪个_联想笔记本按哪个键进入u盘启动
  17. 也谈“为什么中国的程序员总被称为码农?”
  18. 同构数怎么判断_编程:输入1-100以内的一个整数,判断这个数是否是同构数。输出不同的情况...
  19. java 汽车售票_基于jsp的长途汽车售票系统-JavaEE实现长途汽车售票系统 - java项目源码...
  20. 小冰与51CTO的前世今生

热门文章

  1. 3月第4周全球域名商TOP15:万网第四 涨幅居亚
  2. 学习笔记(二)JavaScript基本概念(语法,数据类型,控制语句,函数)
  3. 在Extjs中动态增加控件
  4. SQL Server 2008之DMF
  5. windows socket 简单实例
  6. (ZT)VC++的链接错误LNK2001
  7. 基于GDAL库,读取海洋风场数据(.nc格式)c++版
  8. 常用模块之 time,datetime,random,os,sys
  9. Python 项目实践三(Web应用程序)第四篇
  10. Linux0.11内核剖析--内核体系结构