C# 中如何让自定义校验方法更新参数的可空状态?
数据小陈
给 fileName 参数添加 System.Diagnostics.CodeAnalysis.NotNull 标注。参数可以传入 null,标注告诉编译器:只要方法正常返回,参数就一定非空。Microsoft Learn 对此用法有直接说明。
为什么抛出异常后仍然有警告?
可空性分析已经在工作,否则编辑器不会给出这条提示。调用处不会自动根据自定义方法内部的检查,推导出参数在方法返回后非空。需要用标注声明这个非空后置条件。
修改校验方法
引入命名空间,把 [NotNull] 放在参数上,保留原有校验逻辑:
using System.Diagnostics.CodeAnalysis;
using System.IO;
internal static class ExceptionExtensions
{
extension(FileNotFoundException)
{
internal static void ThrowIfNullOrNotExist(
[NotNull] string? fileName)
{
if (string.IsNullOrWhiteSpace(fileName) || !File.Exists(fileName))
{
throw new FileNotFoundException("File has not been found", fileName);
}
}
}
}
string? 表示允许传入 null 进行校验,[NotNull] 则表示方法正常返回后参数非空。
调用方式保持一致。原示例没有给出 fso 的定义,下面将它显式作为参数传入:
internal static void WriteFile(string? fileName, FileStreamOptions fso)
{
FileNotFoundException.ThrowIfNullOrNotExist(fileName);
using var fs = new FileStream(fileName, fso);
}
在启用可空性分析的上下文中,编译器会把调用后的 fileName 视为非空。如果后续又给它赋了可能为 null 的值,就需要重新判断。
使用时注意什么?
[NotNull]提供静态分析信息,不会增加运行时检查。必须保留实际的判空和抛异常逻辑。- 这个方法返回
void,正常返回时保证参数非空,适合使用[NotNull]。[NotNullWhen(true)]适用于返回bool且在返回true时保证参数非空的方法。 - 原代码的
extension(FileNotFoundException)使用了 C# 14 引入的扩展块语法,需要支持该语法的编译器。如果项目使用较早的语言版本,可以把校验方法写成普通静态方法,参数上的[NotNull]用法相同。扩展成员语法说明
备注:内容仅供参考。
