关于 dotnet-inspect-compatibility
这项技能指导使用 dotnet-inspect 比较 .NET 库版本,并检查 API 与实现变化,涵盖兼容性、行为信号、源码证据和版本选择,适用于升级与迁移评估。
主要功能
- 01比较包、平台和库的 API
- 02匹配不同版本中的类型与成员
- 03检查行为信号变化
- 04比较实现、IL 与 PDB 源码
- 05检查功能开关和包版本
适用场景
- 01升级前评估 API 变化
- 02在新版本中定位类型或成员
- 03筛查分配或异常变化
- 04审查不同构建间的实现变化
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ richlander/ dotnet-inspect --skill dotnet-inspect-compatibility安装后在 Claude Code 中输入/dotnet-inspect-compatibility确认已加载。
详细介绍
dotnet-inspect:兼容性与变更分析
使用此技能判断是否可以安全采用某项变更:了解两个版本之间发生了什么变化,以及某个库公开了哪些接口。此场景涉及多个命令——使用 diff 查看变更,使用 library/package 查看单个版本公开的接口。
dnx dotnet-inspect -y -- <command>
API 接口是否发生变化?
diff 可比较软件包、平台(内置)库或两个本地构建版本之间的版本范围。请根据要回答的问题选择比较视角:
dnx dotnet-inspect -y -- diff --package [email protected] --breaking
dnx dotnet-inspect -y -- diff --platform [email protected] --additive
dnx dotnet-inspect -y -- diff --library old/Foo.dll..new/Foo.dll --changed
迁移工作使用 --breaking,编写发行说明使用 --additive,查看成员原地变更使用 --changed,快速列出变更使用 --name-only。使用 -t TypeName 缩小范围;使用 --all 扩大范围。
对于每侧各有一个 Library 的常规 API 差异比较,两端必须具有相同的程序集名称、区域性和公钥令牌;程序集版本可以不同。CLI 使用适用于网站 Compare 的可移植 Library 比较契约。未经兼容性评估的类型定义或成员变更仍会显示为 其他 API 变更(在 -S Changes --json/--jsonl/--tsv 中标记为 unclassified)。不要将其视为安全或有破坏性;--breaking 和 --additive 只会筛选已评估的分类。
比较未完成或遭拒时会返回非零值,并报告 未比较。缺少泛型约束依赖项时,会保留其检查失败证据。无效的托管映像输入会在 stderr 上报告准入错误。不要将这些结果理解为“没有 API 变更”。多 Library 软件包、-m 筛选、Analysis Diff、Implementation Diff、Finding Transitions 和混合分区请求仍使用现有处理路径。
对于完整的共享单 Library API 结果,请使用未投影的 --json。它会输出 LibraryApiDiffOutcome:outcome 的值为 available、unavailable 或 rejected,并包含完整的 Document 或类型化的非成功端点证据。这取代了先前未投影的 {changes: ...} 视图。显式筛选或分区的 JSON 仍使用展示架构。
使用 --envelope 可获取相同的 Content,以及 Share 和诊断信息;其中包含 schema_version: 1 和 result_kind: "library-api-diff"。允许使用 --all;不允许使用类型/分类筛选、分区、显式详细程度、行/行号窗口及其他 Diff 模式。在任一 JSON 形式中添加 --compact 可压缩空白;如果与投影或其他 Diff 操作一起使用,则会被拒绝。Share 对有序比较端点不可投影。
此项变更不会新增 Evidence 捕获,也不会改变当前的 Browser 投影。
这个 API 坐标去了哪里?
如果问题是某个 Type 或 Member 的对应关系,而不是所有 API 变更,请使用由主体拥有的 --match:
dnx dotnet-inspect -y -- type System.Text.Json.Schema.JsonSchemaExporter \
--package [email protected] --match
dnx dotnet-inspect -y -- member System.Text.Json.JsonSerializer Deserialize:1 \
--package [email protected] --match
端点是两个字面版本,并保持调用方指定的顺序。Member 选择器仅在源端解析;请使用唯一名称、Name:N、Name~digest 或 --index N。目标坐标来自 API 对应关系,因此不要在目标端独立解析相同序号。
此操作匹配声明,而不是访问器主体。当序号选中单例 Property/Event 的访问器时,将拒绝 Foo:1 或 Foo~digest:1 这类选择器;请省略访问器序号以匹配声明。选中重载索引器声明的序号仍然有效。
--tfm 选择一个 API 表面;可选的 --library 仅缩小源 Library 的范围,而 --all 仅将源选择范围扩大到现有的 IncludeAll API 范围。目标声明匹配仍然严格,且独立于常规可访问性变更。使用 --json 获取完整 Content,或使用 --envelope 获取 Content、Share 和诊断信息。请勿将此模式与 History、--at、行投影、投影筛选器、sections、body/source/Analysis 请求或非 Package 来源组合使用。根级 match 与此无关,用于比较实现克隆。
与整个 Library 的 API Diff 类似,type/member --match 目前会报告 share.kind: "nonProjectable",因为可移植场景无法表示有序的对应关系端点。此信封仍可用于查看完整的类型化匹配结果和诊断信息。若要向用户提供一个端点,请单独运行一个由 Package 精确支持的 member ... --share url;该 URL 会打开公共 API Overview,但不会保留对应关系操作。
运行时行为是否发生变化?(分配、异常)
-S "Analysis Diff" 比较两个版本之间主体级信号的差异,而不仅仅是 API 形状。行格式为 Member | Signal | Old | New | Delta,其中 Signal 涵盖 allocations、copies、reflection、throws、catches、finallys、unsafe、constructed-exceptions 和 optimization 形状。借此可以发现跨版本的分配回归或异常覆盖范围变化。(若要了解这些信号在单个版本中的含义,请参阅 performance 和 correctness 技能。)
dnx dotnet-inspect -y -- diff --package [email protected] -S "Analysis Diff"
dnx dotnet-inspect -y -- diff --library old/Foo.dll..new/Foo.dll -S "Analysis Diff" --changed
使用 -S @Diff 组合 API Changes、Analysis Diff 和 Implementation Diff 视图。由于 Finding Transitions 专注于端点确认,其语义无法与这些视图组合,因此仍仅支持精确名称。
使用 Analysis Diff 进行聚合回归排查。若要确认某个分配是否在调用方选定的边界处引入,请解析一个方法并请求原生 Analysis Finding 配对:
dnx dotnet-inspect -y -- diff --package [email protected] \
-t Foo.Parser -m Parse \
--finding analysis.allocation
PairFinding.Added 中 Old=absent 且 New=present,可确认分配的出现。Present、Removed 和 Changed 各自代表不同情况;不要根据聚合分配计数的差异推断分配是否出现。
若要检查某个调用方法中的直接调用边界,请选择调用点生产器:
dnx dotnet-inspect -y -- diff --package [email protected] \
-t Foo.Parser -m Parse \
--finding analysis.call-site
行标识被调用方。PairFinding.Added 可确认出现了新的直接调用;Changed 则报告保留调用的属性变化,例如调用被移入循环。
若要检查某个方法中的确定性不安全操作边界,请选择不安全性生产器:
dnx dotnet-inspect -y -- diff --package [email protected] \
-t Foo.Parser -m Parse \
--finding analysis.unsafety
行标识不安全操作的类型和详细信息。PairFinding.Added 可确认引入;Present 和 Removed 可区分持续存在与消失,而不会将端点局部的 IL 偏移量视为标识。
实现有变化吗?(反编译的 C# + IL + PDB 源码)
--implementation 是精确选择
-S "Implementation Diff" 的常用快捷方式。它会选择由 Research 组合的主体证据,而非默认的 API 兼容性视图。每行标明成员、生成方(C#、IL 或 PDB Source)、变更类型以及由生成方提供的证据。C# 是
反编译文本;PDB Source 是由 Portable-PDB 选择并经校验和验证的文本,可在本地获取或通过 SourceLink 获取。这些通道彼此独立:PDB 源码缺失或获取失败时会如实显示,绝不会取代 C# 通道。使用 -t 和 -m 缩小范围;使用 --table、--tsv 或 --jsonl 输出分列结果。
dnx dotnet-inspect -y -- diff --library old/Foo.dll..new/Foo.dll \
--implementation --pdb-source --repo /path/to/Foo \
-t MyType -m HotPath
--repo 要求提供完全限定的克隆路径。对于
raw.githubusercontent.com SourceLink URL,它会读取 SourceLink 提交中的已提交 blob,并在远程获取源代码正文之前,根据 PDB 校验和进行验证。获取包或 PDB 仍可能需要联网;其他 SourceLink 主机不会使用本地仓库路径。请将这些行视为实现证据,而非语义等价性的证明。
对于每个端点明确选择的一个方法和一个库,--pdb-source 会比较编写的源代码,即使 C# 和 IL 没有变化。
例如,将 1 + 2 改为 3 可以改变源代码,而不改变任何一个编译通道。选定的 Source 通道也会报告未变化或不可用的证据,并保留获取失败信息,而不会将缺失文本视为删除。更广泛的选择仍会为本地已变更的成员补充信息。
可以配置什么?(功能开关)
在 library 或 package --library 上使用 -S Switches,可报告行为以及裁剪/AOT 开关:[FeatureSwitchDefinition]、运行时主机配置选项和 AppContext 开关。
dnx dotnet-inspect -y -- library System.Text.Json -S Switches
要比较的版本
版本解析按源进行。使用 package Foo --versions -n 1 获取最新列出的一个版本行,或使用 package Foo@latest --versions,在答案必须从所有符合条件的已配置源中重新发现,且不能复用旧候选缓存时使用。使用 package Foo --version 1.2.3 验证一个确切版本,并使用 Foo --versions(添加 -n N 获取 N 行,或添加 --preview 获取预发布版本)列出已发布版本。除非明确指定 --include-unlisted,否则不会显示未列出的版本。--versions-with-feed 会保留每个版本/源对,以便在源身份很重要时使用。源声明顺序不代表优先级;如需了解源和凭据工作流,请加载 private-feeds 技能。使用 @ 固定版本:[email protected]、Foo@latest。
对于由调用方驱动的起始点或二分查找工作,先解析一个包含端点、可寻址的向量,然后仅探测你选择的单元格:
dnx dotnet-inspect -y -- package [email protected] --versions
dnx dotnet-inspect -y -- type TargetType --package [email protected] --at '#5'
dnx dotnet-inspect -y -- member TargetType TargetMember --package [email protected] --at 1.6.0
dnx dotnet-inspect -y -- diff --history --package [email protected] \
--type TargetType --members --at first --at last
dnx dotnet-inspect -y -- diff --history --package [email protected] \
--type TargetType --member TargetMember \
--finding analysis.unsafety --at first --at last
--at 接受确切版本、从 1 开始计数的 #N、first 或 last。解析向量不会下载所有包;只会获取选定的探测目标。搜索策略和边界由 Agent 决定。若要查找可安全复现的当前起始点,请从有问题的版本开始向前回溯,直到首次确认问题不存在;仅当已知某个谓词具有单调性时,才使用二分查找。
在线 API/历史版本范围支持已配置的文件夹和 HTTP 源。发现结果必须完整,并且每次探测只能从报告过对应坐标的源获取内容。这些向量仅列出已列出的版本;使用 --include-unlisted 列出的元数据可能具有不同的序号。若要检查未列出的坐标,请使用确切版本固定。本地载荷缓存会保留已配置的授权信息;HTTP 载荷使用临时存储,并会在之后的调用中重新下载。
Diff History 会在同一向量上呈现 Evaluations 和 Transitions。省略 --at 可评估全部样本;重复指定它可设置显式检查点;或使用 --max-probes 进行自适应二分查找。添加 --sample-percent P 可进行相对于总体的确定性抽样调查,也可选择使用 --max-probes 设置上限。使用 --major-versions 可为每个主版本选择一个代表版本:API 发现会选择第一个稳定版本;对于仅有预览版本的主版本,则回退到最新的预发布版本;Analysis 发现则会选择每个主版本中最新的符合条件版本。使用 --type-presence、--members 或 --attributes 选择以类型为重点的普查(分别是 api.type、api.member 和 api.attribute 的别名)。向 api.member 添加 --member,即可跟踪一个确切的成员身份。同一成员选择器可将 analysis.allocation、analysis.call-site 和 analysis.unsafety 历史范围限定为一个方法体。
跨越间隔的转换是所选探测点上的证据,并不代表对确切引入或移除版本的判断。
在线建议会保留源/配置、TFM、预发布版本和可见性选项,因此下一次探测可以从不同的工作目录运行。
范围和单点探测可以确定候选边界。请使用 Metadata 的实际 Finding 比较确认相邻版本对,而不要根据探测文本推断引入情况:
dnx dotnet-inspect -y -- diff \
--package [email protected] \
-t System.Text.Json.Schema.JsonSchemaExporter \
-S "Finding Transitions"
引入边界是满足 PairFinding.Added、Old=absent 和 New=present 的一行。PairFinding.Present 表示目标在两个端点都存在;对于类型目标,如果没有行,则表示两个端点都不存在。使用 -m Type.Member:1 检查 API 成员边界。对于相应的 Analysis 边界,使用 --finding analysis.allocation、--finding analysis.call-site 或 --finding analysis.unsafety,并且只能指定一个方法目标。
使用 --finding csharp.line 或 --finding il.op,并且只能指定一个方法目标,以检查原生实现普查的转换。这些视角会保留完整、缺失和失败的结果,包括新增或移除的方法。