可空引用类型审计工具Skill nullable-audit

这是一个用于.NET开发的技能,旨在审计代码库中可为空引用类型的采用情况,分析编译警告,并提供迁移建议,帮助开发者提高代码质量。关键词包括:.NET、可为空引用类型、代码审计、编译警告、迁移建议、C#开发、代码健壮性。

后端开发 0 次安装 0 次浏览 更新于 3/11/2026

name: 可为空引用类型审计 description: 分析可为空引用类型采用情况,包括警告细分和迁移建议 argument-hint: “[–project <name>] [–detailed] [–warnings]” allowed-tools: Bash, Read, Glob, Grep, AskUserQuestion

/dotnet:可为空引用类型审计

分析代码库中可为空引用类型(NRT)的采用情况,提供详细警告细分和迁移建议。

参数

$ARGUMENTS 解析参数:

标志 描述 默认值
--project <path> 目标特定项目(模糊匹配) 所有项目
--detailed 显示按文件细分 false
--warnings 显示所有可为空警告 false

工作流程

第1步:扫描项目配置

检查项目文件中的可为空状态:

# 查找所有项目文件
find . -name "*.csproj" -type f

# 检查是否为可为空启用
grep -l "<Nullable>enable</Nullable>" **/*.csproj
grep -l "<Nullable>disable</Nullable>" **/*.csproj
grep -l "<Nullable>warnings</Nullable>" **/*.csproj
grep -l "<Nullable>annotations</Nullable>" **/*.csproj

检查 Directory.Build.props 以获取解决方案范围内的设置。

第2步:扫描源文件

对于没有解决方案范围内可为空的项目:

# 查找带有 #nullable 指令的文件
grep -r "#nullable enable" --include="*.cs" .
grep -r "#nullable disable" --include="*.cs" .
grep -r "#nullable restore" --include="*.cs" .

统计总 .cs 文件与可为空启用文件的比率。

第3步:收集可为空警告

构建并捕获可为空警告:

dotnet build 2>&1 | grep -E "CS86[0-9]{2}|CS87[0-9]{2}"

按警告类型分类:

  • CS8600:转换 null 字面量
  • CS8601:可能的空引用赋值
  • CS8602:解除引用可能为空引用
  • CS8603:可能的空引用返回
  • CS8604:可能的空引用参数
  • CS8618:非空字段未初始化
  • CS8625:无法将 null 转换为非空
  • CS8765:参数的可空性不匹配

第4步:生成报告

输出格式

摘要报告:

可为空引用类型审计

解决方案:MyApp.sln
项目数:12

┌─────────────────────────────────────────────────────────────┐
│ 可为空采用状态                                              │
├─────────────────────────────────────────────────────────────┤
│ 项目                        状态        文件    问题数      │
├─────────────────────────────────────────────────────────────┤
│ src/MyApp.Core               启用        45       12        │
│ src/MyApp.Api                启用        32       8         │
│ src/MyApp.Infrastructure     启用        28       23        │
│ src/MyApp.Domain             启用        18       0         │
│ tests/MyApp.Tests            禁用        42       N/A       │
│ src/MyApp.Legacy             (未设置)    15       N/A       │
└─────────────────────────────────────────────────────────────┘

采用率:83% (10/12 个项目启用可为空)
带有 NRT 的文件:123/180 (68%)

警告摘要:
  CS8602 (空解除引用):        18
  CS8618 (未初始化字段):      12
  CS8604 (空参数):            8
  CS8600 (空赋值):            5
  总可为空警告:                43

详细报告 (–detailed):

可为空引用类型审计 (详细)

═══════════════════════════════════════════════════════════════
项目:src/MyApp.Infrastructure
可为空:启用 (项目级别)
═══════════════════════════════════════════════════════════════

带有警告的文件:
  src/MyApp.Infrastructure/Repositories/UserRepository.cs
    - CS8602:第 42 行 - _context.Users 可能为空
    - CS8602:第 67 行 - user.Email 可能为空
    - CS8618:第 12 行 - _context 未初始化

  src/MyApp.Infrastructure/Services/CacheService.cs
    - CS8604:第 28 行 - 参数可能为空
    - CS8600:第 35 行 - null 赋值

  ... (更多文件)

无警告的文件 (干净):
  src/MyApp.Infrastructure/Extensions/ServiceCollectionExtensions.cs
  src/MyApp.Infrastructure/DependencyInjection.cs
  ... (15 个更多)

───────────────────────────────────────────────────────────────
项目:src/MyApp.Legacy
可为空:未启用
───────────────────────────────────────────────────────────────

此项目未启用可为空引用类型。
要启用,请添加到 .csproj:
  <PropertyGroup>
    <Nullable>enable</Nullable>
  </PropertyGroup>

或使用 #nullable enable 指令按文件启用。

警告报告 (–warnings):

按类别分类的可为空警告

CS8602:解除引用可能为空引用 (18 个警告)
────────────────────────────────────────────────────────────────
  src/MyApp.Infrastructure/Repositories/UserRepository.cs:42
    var name = user.Name.ToUpper();  // user.Name 可能为空

  src/MyApp.Api/Controllers/UsersController.cs:67
    return Ok(result.Data.Items);    // result.Data 可能为空

  ... (16 个更多)

  修复:添加空检查或使用空条件运算符 (?.)
  示例:var name = user.Name?.ToUpper() ?? string.Empty;

CS8618:非空字段必须初始化 (12 个警告)
────────────────────────────────────────────────────────────────
  src/MyApp.Core/Models/User.cs:12
    public string Email { get; set; }  // 未初始化

  src/MyApp.Core/Models/Order.cs:8
    public Customer Customer { get; set; }  // 未初始化

  ... (10 个更多)

  修复选项:
    1. 用默认值初始化:public string Email { get; set; } = string.Empty;
    2. 设为可为空:public string? Email { get; set; }
    3. 使用 required 修饰符 (C# 11+):public required string Email { get; set; }
    4. 在构造函数中初始化

CS8604:可能的空引用参数 (8 个警告)
────────────────────────────────────────────────────────────────
  ... (详情)

迁移建议

基于审计结果,提供建议:

迁移建议

1. 立即执行 (高影响,低难度)
   ─────────────────────────────────────
   - 在 src/MyApp.Legacy 中启用可为空 (15 个文件,预计 ~20 个警告)
   - 在测试项目中启用可为空 (可选但推荐)

2. 快速解决 (可自动修复)
   ─────────────────────────────────────
   - CS8618 警告:添加 = null! 或 required 修饰符 (12 个警告)
   - CS8625 警告:修复 null 字面量赋值 (5 个警告)

   运行:/dotnet:fix-warnings --category nullable

3. 需审核 (上下文依赖)
   ─────────────────────────────────────
   - CS8602 解除引用警告:添加空检查 (18 个警告)
   - CS8604 参数警告:验证输入 (8 个警告)

   这些需要理解 null 是否有效。

4. 可选清理
   ─────────────────────────────────────
   - 移除启用项目中的 #nullable disable 指令 (3 个文件)
   - 考虑在测试项目中启用可为空

估计工作量:2-4 小时完成完整迁移

可为空状态参考

设置 注解 警告
enable
disable
warnings
annotations

示例

# 基本审计摘要
/dotnet:可为空引用类型审计

# 详细按文件细分
/dotnet:可为空引用类型审计 --detailed

# 显示所有可为空警告及修复
/dotnet:可为空引用类型审计 --warnings

# 审计特定项目
/dotnet:可为空引用类型审计 --project MyApp.Core

与其他命令集成

审计后,使用以下命令处理发现:

# 自动修复可能的警告
/dotnet:fix-warnings --category nullable

# 在项目中启用可为空 (手动编辑或使用 Edit 工具)
# 将 <Nullable>enable</Nullable> 添加到 .csproj

# 重新构建以查看剩余警告
/dotnet:build