PAYATHON 2026

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] 用法相同。扩展成员语法说明

备注:内容仅供参考。