前言
在前面的文章中(《可空引用类型》),我们介绍过编译器会帮我们检查空引用,但是仅仅是警告。最好的方式还是在运行时用卫语句进行检查:
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
利用这些属性,可以让编译器“神奇地”填充它们,帮助我们轻松获取调用者信息。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 xxx@163.com 举报,一经查实,本站将立刻删除。