mcpField
D
dotnet-version-upgrade

dotnet-version-upgrade

github.com/wshaddix开发8678 次安装35 周前更新
代码仓库

关于 dotnet-version-upgrade

面向规划 .NET 版本迁移的开发者,涵盖受支持版本和预览版本。提供三种升级路径,以及 TFM、包更新、破坏性更改、弃用 API 和验证方面的指导。

主要功能

  1. 01在三种升级路径中作出选择
  2. 02更新 TFM、SDK 和包
  3. 03检测破坏性更改与弃用 API
  4. 04通过构建和测试验证迁移
  5. 05在防护措施下探索预览版升级

适用场景

  1. 01规划 LTS 到 LTS 的直接迁移
  2. 02因依赖限制分阶段升级
  3. 03在生产环境之外评估预览版
  4. 04检查库升级的 API 兼容性

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-version-upgrade

安装后在 Claude Code 中输入/dotnet-version-upgrade确认已加载。

详细介绍

dotnet-version-upgrade

.NET 版本升级规划与执行的综合指南。此技能使用 [skill:dotnet-version-detection] 的结构化输出(当前 TFM、SDK 版本、预览版标志),并根据三个定义的升级路径提供可操作的升级指导。涵盖 TFM 迁移、包更新、重大更改检测、已弃用 API 替换和测试验证。

不在范围内: TFM 检测逻辑(由 [skill:dotnet-version-detection] 负责)、多目标项目设置和 polyfill 策略(参见 [skill:dotnet-multi-targeting])、云部署配置、CI/CD 管道更改。

交叉参考:[skill:dotnet-version-detection],用于 TFM 解析和版本矩阵;[skill:dotnet-multi-targeting],用于在迁移期间保持向后兼容性的 polyfill 优先多目标策略。


升级路径

根据项目需求和生态系统约束,选择合适的升级路径。

路径迁移方案使用场景风险级别
生产(默认)net8.0 -> net10.0LTS 到 LTS,适用于大多数应用的推荐方案低——两个版本均为 LTS,支持周期较长
分阶段生产net8.0 -> net9.0 -> net10.0生态系统依赖要求逐步迁移时中——中间的 STS 版本支持周期较短
实验性net10.0 -> net11.0 (preview)在非生产环境中探索即将推出的功能高——预览版 API 可能发生变化或被移除
路径选择决策流程
  1. 所有 NuGet 依赖项是否都支持目标 LTS?是 -> 生产路径(直接从 LTS 迁移到 LTS)。
  2. 是否有任何依赖项要求使用中间版本?是 -> 分阶段生产路径。
  3. 是否要为研发或概念验证探索预览功能?是 -> 实验性路径。

生产路径:LTS 到 LTS(net8.0 -> net10.0)

这是推荐的默认升级方案。.NET 8 和 .NET 10 均为长期支持版本,可实现稳定迁移,且重大更改均有完善文档说明。

升级检查清单

步骤 1:更新项目文件中的 TFM


<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
</PropertyGroup>


<PropertyGroup>
  <TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

对于包含共享属性的解决方案:


<PropertyGroup>
  <TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

步骤 2:更新 global.json SDK 版本

{
  "sdk": {
    "version": "10.0.100",
    "rollForward": "latestFeature"
  }
}

步骤 3:更新 NuGet 包

使用 dotnet-outdated 检测过时的包,并确定哪些包需要更新以兼容 TFM:

# Install dotnet-outdated as a global tool
dotnet tool install -g dotnet-outdated-tool

# Check for outdated packages across the solution
dotnet outdated

# Check a specific project
dotnet outdated MyProject/MyProject.csproj

# Auto-upgrade to latest stable versions
dotnet outdated --upgrade

# Upgrade only to the latest minor/patch (safer)
dotnet outdated --upgrade --version-lock major

对于 ASP.NET Core 共享框架包,更新版本引用,使其与目标 TFM 匹配:

<ItemGroup>
  
  <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.*" />
  <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.*" />
</ItemGroup>

步骤 4:检查重大更改

# Build to surface warnings and errors
dotnet build --warnaserror

# Run analyzers for deprecated API usage
dotnet build /p:TreatWarningsAsErrors=true

查阅官方重大更改列表:

步骤 5:替换已弃用的 API

从 net8.0 升级到 net10.0 时的常见替换方案:

已弃用项替换方案备注
BinaryFormatterSystem.Text.Json 或 MessagePack从 net9.0 开始,BinaryFormatter 会引发 PlatformNotSupportedException
Thread.Abort()使用 CancellationToken 进行协作式取消Thread.Abort() 会引发 PlatformNotSupportedException
WebRequest / HttpWebRequest通过 IHttpClientFactory 使用 HttpClient已过时(SYSLIB0014),请迁移到 HttpClient

建议的现代化改进(并非已弃用,但可提升性能和 AOT 就绪度):

模式改进方案备注
未使用源生成的 Regex[GeneratedRegex] 特性源生成的正则表达式速度更快,并且兼容 AOT

步骤 6:运行测试并验证

# Run full test suite
dotnet test --configuration Release

# Enable trim/AOT analyzers to surface compatibility warnings without publishing
dotnet build --configuration Release /p:EnableTrimAnalyzer=true /p:EnableAotAnalyzer=true
.NET Upgrade Assistant

.NET Upgrade Assistant 可自动完成部分迁移流程。它最适用于包含多个项目的大型解决方案。

# Install as a global tool
dotnet tool install -g upgrade-assistant

# Analyze a project (non-destructive, reports recommendations)
upgrade-assistant analyze MyProject/MyProject.csproj

# Perform the upgrade (modifies files)
upgrade-assistant upgrade MyProject/MyProject.csproj

何时使用 Upgrade Assistant:

  • 包含多个项目且依赖关系图复杂的大型解决方案
  • 从旧版 .NET Framework 迁移到现代 .NET
  • 在提交升级之前需要全面分析依赖关系

限制:

  • 可能无法处理所有破坏性变更——仍需手动审查
  • 自定义 MSBuild 扩展和第三方构建工具可能需要手动调整
  • 不会更新运行时行为差异——完善的测试覆盖至关重要
  • 对依赖项较少的小型项目没有必要(手动更新 TFM 更简单)

分阶段生产路径:net8.0 -> net9.0 -> net10.0

当生态系统限制阻碍直接从一个 LTS 版本迁移到下一个 LTS 版本时,请使用分阶段路径。通过 .NET 9(STS)分阶段迁移,可以实现渐进式迁移。

何时分阶段迁移到 .NET 9
  • **第三方包兼容性:**某个关键依赖项仅支持 net9.0(尚不支持 net10.0),而你需要立即从 net8.0 升级。
  • **大量破坏性变更:**从 net8.0 升级到 net10.0 涉及的破坏性变更过多,无法一次性处理;分步迁移可降低风险。
  • **渐进式验证:**你希望在继续迁移之前,逐步验证每个阶段的行为变更。
.NET 9 背景

.NET 9 是一个标准支持期限(STS)版本:

  • **正式发布:**2024 年 11 月
  • **支持结束:**2026 年 5 月(自正式发布起 18 个月)
  • **C# 版本:**C# 13

由于 .NET 9 即将结束支持,请勿停留在 net9.0。请在开始第一阶段迁移之前,规划好第二阶段迁移(net9.0 -> net10.0)。

分阶段升级检查清单

第一阶段:net8.0 -> net9.0

  1. 在 .csproj / Directory.Build.props 中将 TFM 更新为 net9.0
  2. 将 global.json 中的 SDK 更新为 9.0.xxx
  3. 运行 dotnet outdated --upgrade 更新包
  4. 查看 .NET 9 破坏性变更
  5. 替换由 SYSLIB 诊断和 CS0618 警告指出的已弃用 API(例如,BinaryFormatter -> System.Text.Json)
  6. 运行 dotnet test --configuration Release 进行验证
  7. 部署到预发布环境,并通过监控在生产环境中验证

第二阶段:net9.0 -> net10.0

  1. 在 .csproj / Directory.Build.props 中将 TFM 更新为 net10.0
  2. 将 global.json 中的 SDK 更新为 10.0.xxx
  3. 再次运行 dotnet outdated --upgrade
  4. 查看 .NET 10 破坏性变更
  5. 替换 net9.0 到 net10.0 之间引入的其他已弃用 API
  6. 运行 dotnet test --configuration Release 进行验证
  7. 部署到预发布环境,并移除任何针对 net9.0 的变通方案

**时间安排建议:**在 .NET 9 支持期限内(2026 年 5 月之前)完成两个阶段的迁移。在已停止支持的 STS 版本上运行生产工作负载,会使你面临未修补的安全漏洞。


实验路径:net10.0 -> net11.0(预览版)

用于非生产环境中探索即将推出的功能。目前 .NET 11 仍处于预览阶段,其 API 在正式发布前可能会变更或移除。

安全措施
  • **仅限非生产环境。**请勿将目标为预览版的代码部署到生产环境。
  • **使用独立分支或项目。**将实验工作与生产代码库隔离。
  • **固定预览版 SDK。**使用 global.json 锁定特定预览版 SDK,以避免不同预览版本之间出现未察觉的行为变更。
  • **预期不同预览版本之间会有破坏性变更。**标记为 [RequiresPreviewFeatures] 的 API 可能会在不同预览版本之间改变形式。
启用预览功能

步骤 1:安装预览版 SDK

# Verify installed SDKs
dotnet --list-sdks

# Example: 11.0.100-preview.1.xxxxx should appear

步骤 2:在 global.json 中固定使用预览版 SDK

{
  "sdk": {
    "version": "11.0.100-preview.1.25120.13",
    "rollForward": "disable"
  }
}

使用 "rollForward": "disable",防止在不同预览版之间自动升级 SDK 版本。

步骤 3:设置 TFM 并启用预览功能

<PropertyGroup>
  <TargetFramework>net11.0</TargetFramework>
  <LangVersion>preview</LangVersion>
  <EnablePreviewFeatures>true</EnablePreviewFeatures>
</PropertyGroup>

步骤 4:启用 runtime-async(可选)

Runtime-async 将 async/await 从编译器生成的状态机迁移到运行时级别执行,从而减少分配并提升异步密集型工作负载的性能:

<PropertyGroup>
  <TargetFramework>net11.0</TargetFramework>
  <LangVersion>preview</LangVersion>
  <EnablePreviewFeatures>true</EnablePreviewFeatures>
  <Features>$(Features);runtime-async=on</Features>
</PropertyGroup>

Runtime-async 需要同时启用 EnablePreviewFeatures 和 Features 标志。它属于实验性功能,在正式发布前可能会发生重大变化。

实验性升级检查清单
  1. 安装 .NET 11 预览版 SDK,并在 global.json 中使用 "rollForward": "disable" 固定版本
  2. 将 TFM 更新为 net11.0,并设置 <LangVersion>preview</LangVersion> + <EnablePreviewFeatures>true</EnablePreviewFeatures>
  3. 运行 dotnet outdated,检查包与预览版 TFM 的兼容性
  4. 构建并检查警告——预览版 SDK 可能会报告新的 SYSLIB 诊断或 CA2252(预览功能用法)
  5. 替换新分析器版本发现的所有已弃用 API
  6. 运行 dotnet test 进行验证——预计部分第三方包尚不支持预览版 TFM
  7. 记录发现的问题,以便规划后续生产环境升级
探索 .NET 11 预览版的内容
功能领域说明
Runtime-async性能运行时级别的 Async/await;需要选择启用
Zstandard 压缩I/OSystem.IO.Compression.Zstandard;速度比 Brotli 快 2-7 倍
BFloat16数值计算面向 AI/ML 工作负载的 System.Numerics.BFloat16
Happy Eyeballs网络用于双栈 IPv4/IPv6 的 ConnectAlgorithm.Parallel
C# 15 预览功能语言集合表达式参数(with() 语法)
WASM 上的 CoreCLR运行时Blazor WASM 中 Mono 的实验性替代方案

破坏性变更检测

在任何升级过程中,系统地识别和解决破坏性变更。

构建时检测
# Clean build to surface all warnings (not just incremental)
dotnet clean && dotnet build --no-incremental

# Treat warnings as errors to catch deprecation notices
dotnet build /p:TreatWarningsAsErrors=true

# List specific obsolete API warnings
dotnet build 2>&1 | grep -E "CS0618|CS0612"
  • CS0618:使用带有消息的 [Obsolete] 成员
  • CS0612:使用不带消息的 [Obsolete] 成员
  • CS8073:表达式始终计算为同一值(类型行为变更)
分析器诊断

启用 .NET 分析器以检测其他问题:

<PropertyGroup>
  <EnableNETAnalyzers>true</EnableNETAnalyzers>
  <AnalysisLevel>latest-recommended</AnalysisLevel>
</PropertyGroup>

升级时需关注的分析器类别:

  • CA1422:平台兼容性(目标平台上已移除 API)
  • CA1416:未使用防护措施的平台特定 API
  • CA2252:选择使用预览功能
  • SYSLIB0XXX:已弃用系统 API 的诊断(例如,针对 BinaryFormatter 的 SYSLIB0011)
API 差异工具

对于库作者,可使用 API 兼容性工具验证公共接口变更:

# Package validation detects breaking changes against a baseline
dotnet pack /p:EnablePackageValidation=true /p:PackageValidationBaselineVersion=1.0.0

# Standalone API comparison
dotnet tool install -g Microsoft.DotNet.ApiCompat.Tool
apicompat --left-assembly bin/Release/net8.0/MyLib.dll \
          --right-assembly bin/Release/net10.0/MyLib.dll

有关 API 兼容性验证工作流的详细信息(包括抑制文件和 CI 集成),请参阅 [skill:dotnet-multi-targeting]。


包更新策略

dotnet-outdated

dotnet-outdated 工具全面展示包的过时情况:

# Install
dotnet tool install -g dotnet-outdated-tool

# Show all outdated packages with current vs latest versions
dotnet outdated

# Lock major version, show only minor/patch updates (safer incremental upgrades)
dotnet outdated --version-lock major

# Auto-upgrade with version locking to avoid unexpected major bumps
dotnet outdated --upgrade --version-lock major

# Output as JSON for CI integration
dotnet outdated --output-format json
中央包管理

对于使用中央包管理(Directory.Packages.props)的解决方案,可集中更新版本:


<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <ItemGroup>
    
    <PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.*" />
    <PackageVersion Include="Microsoft.Extensions.Http" Version="10.*" />
    <PackageVersion Include="Microsoft.Extensions.Logging" Version="10.*" />
    
    <PackageVersion Include="Serilog" Version="4.*" />
  </ItemGroup>
</Project>

Directory.Packages.props 会从项目目录开始逐级向上解析。在单体仓库结构中,请确认嵌套的 Directory.Packages.props 文件没有遮蔽根目录级别的配置。

ASP.NET Core 共享框架包

ASP.NET Core 共享框架包的主版本必须与目标 TFM 一致。以下两种方式均有效:

<ItemGroup>
  
  <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.*" />

  
  <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.1" />
</ItemGroup>

为确保 CI 的确定性,建议固定版本;在探索性升级期间,使用浮动版本也很有用。无论采用哪种方式,主版本必须与 TFM 一致(例如,net10.0 对应 10.x)。


Agent 注意事项

  1. 未经验证生态系统兼容性,不要跳过 .NET 9。 虽然从 LTS 升级到 LTS(net8.0 -> net10.0)是推荐的默认做法,但某些第三方包可能只支持将 net9.0 作为中间步骤。选择升级路径前,请检查包的兼容性。

  2. 不要在生产工作负载中使用预览版 SDK。 .NET 11 预览版 API 不稳定,并且会在不同预览版之间发生变化。请将实验性工作隔离在单独的分支或项目中,并固定预览版 SDK 的版本。

  3. 不要假设 .NET 9 STS 的支持期为 12 个月。 STS 生命周期为 GA 发布后 18 个月。.NET 9 于 2024 年 11 月发布 GA,因此支持将于 2026 年 5 月结束。请始终根据实际 GA 日期计算,而非根据发布年份计算。

  4. 确保 ASP.NET 共享框架包的主版本与 TFM 匹配。 Microsoft.AspNetCore.Mvc.Testing 等包的主版本必须与项目 TFM 对齐(例如,net10.0 对应 10.x)。为确保 CI 构建具有确定性,请固定确切版本;在探索性升级期间,也可以使用通配符(例如,10.*)。

  5. 不要重新实现 TFM 检测。 此技能使用 [skill:dotnet-version-detection] 提供的结构化输出。切勿解析 .csproj 文件来确定当前版本——请使用检测技能的输出(TFM、C# 版本、SDK 版本、警告)。

  6. 不要将 dotnet-outdated --upgrade 视为完整解决方案。 它会更新包版本,但不会处理这些包中的重大 API 更改。升级包后,务必构建、测试并查看变更日志。

  7. 不要在预览版 SDK 中使用 "rollForward": "latestMajor"。 这可能会悄然切换到具有破坏性更改的其他预览版本。对于预览版 SDK,请使用 "rollForward": "disable",以确保构建可复现。

  8. 不要忽略 Directory.Packages.props 的层级结构。 在 monorepo 结构中,嵌套的 Directory.Packages.props 文件会覆盖父级配置。升级时,请从项目目录向上查找所有可能影响包解析的 Directory.Packages.props 文件。

  9. 升级时不要忽略 SYSLIB 诊断代码。 这些系统级过时警告(例如,BinaryFormatter 对应的 SYSLIB0011、WebRequest 对应的 SYSLIB0014)表示相关 API 在较新的 TFM 上会在运行时抛出异常,而不仅仅是编译时警告。


先决条件

  • 已安装目标 TFM 对应的 .NET SDK(例如,升级到 net10.0 需要 .NET 10 SDK)
  • dotnet-outdated-tool(用于检测过时的包):dotnet tool install -g dotnet-outdated-tool
  • upgrade-assistant(可选,用于自动迁移):dotnet tool install -g upgrade-assistant
  • [skill:dotnet-version-detection] 的输出(当前 TFM、SDK 版本、预览标记)

参考资料

最后验证日期:2026-02-12

评论

支持 Markdown