dotnet-build-analysis

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

dotnet-build-analysis

.NET构建分析

Help agents interpret and act on MSBuild build output. Covers error code prefixes, NuGet restore failures, analyzer warning interpretation, multi-targeting build differences, and "works locally, fails in CI" diagnosis patterns. Each subsection includes example output, diagnosis steps, and a fix pattern.
帮助Agent解读并处理MSBuild构建输出,涵盖错误代码前缀、NuGet还原失败、分析器警告解读、多目标框架构建差异,以及「本地正常运行、CI构建失败」的诊断模式。每个小节都包含示例输出、诊断步骤和修复方案。

Scope

适用范围

  • MSBuild error code prefix interpretation (CS, MSB, NU, CA, IDE, NETSDK)
  • NuGet restore failure diagnosis and resolution
  • Analyzer warning triage and suppression guidance
  • CI vs local build drift diagnosis
  • MSBuild错误代码前缀解读(CS、MSB、NU、CA、IDE、NETSDK)
  • NuGet还原失败的诊断与解决
  • 分析器警告分类处理与抑制指导
  • CI与本地构建差异的诊断

Out of scope

不适用范围

  • Writing or modifying .csproj files -- see [skill:dotnet-csproj-reading]
  • Project structure decisions -- see [skill:dotnet-project-structure]
  • Common agent code mistakes -- see [skill:dotnet-agent-gotchas]
  • 编写或修改.csproj文件——请参考[skill:dotnet-csproj-reading]
  • 项目结构决策——请参考[skill:dotnet-project-structure]
  • Agent常见代码错误——请参考[skill:dotnet-agent-gotchas]

Prerequisites

前置条件

.NET 8.0+ SDK. MSBuild (included with .NET SDK). Understanding of SDK-style project format.
Cross-references: [skill:dotnet-agent-gotchas] for common code mistakes that cause build errors, [skill:dotnet-csproj-reading] for project file structure and modification, [skill:dotnet-project-structure] for project organization and SDK selection.

.NET 8.0+ SDK(MSBuild已随.NET SDK包含)。了解SDK风格项目格式。
交叉参考:[skill:dotnet-agent-gotchas] 介绍导致构建错误的常见Agent代码错误;[skill:dotnet-csproj-reading] 介绍项目文件结构与修改;[skill:dotnet-project-structure] 介绍项目组织与SDK选择。

Error Code Prefixes

错误代码前缀

MSBuild output uses standardized prefixes to indicate the error source. Understanding the prefix tells you which system produced the error and where to look for fixes.
MSBuild输出使用标准化前缀标识错误来源,理解前缀可帮助定位错误产生的系统及修复方向。

CS -- C# Compiler Errors and Warnings

CS — C#编译器错误与警告

Produced by the Roslyn C# compiler. These are language-level issues in source code.
Example output:
src/MyApp.Api/Services/OrderService.cs(42,17): error CS0246: The type or namespace name 'OrderDto' could not be found (are you missing a using directive or an assembly reference?)
src/MyApp.Api/Models/User.cs(15,9): warning CS8618: Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
Diagnosis:
  1. Parse the file path and line number from the error --
    src/MyApp.Api/Services/OrderService.cs
    line 42, column 17.
  2. CS0246 means a type is missing. Check: is the type defined? Is the namespace imported? Is the project referencing the assembly that contains it?
  3. CS8618 is a nullable reference type warning. The property needs a
    required
    modifier, nullable annotation (
    string?
    ), or constructor initialization.
Fix pattern:
  • CS0xxx (syntax/type errors): Fix source code at the indicated location. Add
    using
    directives, fix type names, add missing references.
  • CS8xxx (nullable warnings): Add null annotations, null checks, or
    required
    modifiers. Do NOT suppress with
    #pragma
    or
    !
    operator.
由Roslyn C#编译器生成,属于源代码中的语言级问题。
示例输出:
src/MyApp.Api/Services/OrderService.cs(42,17): error CS0246: The type or namespace name 'OrderDto' could not be found (are you missing a using directive or an assembly reference?)
src/MyApp.Api/Models/User.cs(15,9): warning CS8618: Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
诊断:
  1. 解析错误中的文件路径和行号——
    src/MyApp.Api/Services/OrderService.cs
    第42行第17列。
  2. CS0246表示找不到类型,检查:该类型是否已定义?是否导入了对应的命名空间?项目是否引用了包含该类型的程序集?
  3. CS8618是可为空引用类型警告,该属性需要添加
    required
    修饰符、可为空注解(
    string?
    )或在构造函数中初始化。
修复方案:
  • CS0xxx(语法/类型错误):在指定位置修复源代码,添加
    using
    指令、修正类型名称、添加缺失的引用。
  • CS8xxx(可为空警告):添加空注解、空检查或
    required
    修饰符,请勿使用
    #pragma
    !
    运算符抑制警告。

MSB -- MSBuild Engine Errors

MSB — MSBuild引擎错误

Produced by the MSBuild build engine itself. These indicate project file problems, target failures, or build system misconfiguration.
Example output:
error MSB4019: The imported project "C:\Program Files\dotnet\sdk\9.0.100\Microsoft\VisualStudio\v17.0\WebApplications\Microsoft.WebApplication.targets" was not found. Confirm that the expression in the Import declaration "..." is correct.
error MSB3644: The reference assemblies for .NETFramework,Version=v4.8 were not found. You might need to install the developer pack for this framework version.
Diagnosis:
  1. MSB4019: An MSBuild
    .targets
    file is missing. This usually means wrong SDK type, missing workload, or corrupt SDK installation.
  2. MSB3644: Targeting a framework version whose targeting pack is not installed. Common when a project targets .NET Framework but only .NET (Core) SDK is installed.
Fix pattern:
  • MSB4019: Verify
    <Project Sdk="...">
    is correct (e.g.,
    Microsoft.NET.Sdk.Web
    for ASP.NET Core). Run
    dotnet workload list
    and install missing workloads.
  • MSB3xxx: Check
    <TargetFramework>
    value. Ensure the required SDK or targeting pack is installed.
由MSBuild构建引擎本身生成,表明项目文件存在问题、目标执行失败或构建系统配置错误。
示例输出:
error MSB4019: The imported project "C:\Program Files\dotnet\sdk\9.0.100\Microsoft\VisualStudio\v17.0\WebApplications\Microsoft.WebApplication.targets" was not found. Confirm that the expression in the Import declaration "..." is correct.
error MSB3644: The reference assemblies for .NETFramework,Version=v4.8 were not found. You might need to install the developer pack for this framework version.
诊断:
  1. MSB4019:缺失MSBuild
    .targets
    文件,通常意味着SDK类型错误、缺失工作负载或SDK安装损坏。
  2. MSB3644:目标框架版本的引用程序集未安装,常见于项目目标为.NET Framework但仅安装了.NET(Core)SDK的情况。
修复方案:
  • MSB4019:验证
    <Project Sdk="...">
    配置正确(例如ASP.NET Core项目使用
    Microsoft.NET.Sdk.Web
    ),运行
    dotnet workload list
    并安装缺失的工作负载。
  • MSB3xxx:检查
    <TargetFramework>
    值,确保已安装所需的SDK或目标包。

NU -- NuGet Errors and Warnings

NU — NuGet错误与警告

Produced by the NuGet package manager during restore or pack operations.
Example output:
error NU1101: Unable to find package Newtonsoft.Json.Extensions. No packages exist with this id in source(s): nuget.org
warning NU1603: Microsoft.EntityFrameworkCore 9.0.0 depends on Microsoft.Extensions.Caching.Memory (>= 9.0.0) but version Microsoft.Extensions.Caching.Memory 8.0.1 was resolved. Approve the package to suppress this warning.
error NU1605: Detected package downgrade: Microsoft.Extensions.Logging from 9.0.0 to 8.0.1. Reference the package directly from the project to select a different version.
Diagnosis:
  1. NU1101: Package ID does not exist. Check spelling, verify the package source is configured, check if the package was renamed or deprecated.
  2. NU1603: Transitive dependency version conflict. A package wants a newer version than what is resolved.
  3. NU1605: Explicit downgrade detected. Two packages require different versions of the same dependency.
Fix pattern:
  • NU1101: Fix the package name. Search nuget.org for the correct ID.
  • NU1603/NU1605: Add a direct
    <PackageReference>
    for the conflicting package at a compatible version, or use central package management to pin versions.
由NuGet包管理器在还原或打包操作时生成。
示例输出:
error NU1101: Unable to find package Newtonsoft.Json.Extensions. No packages exist with this id in source(s): nuget.org
warning NU1603: Microsoft.EntityFrameworkCore 9.0.0 depends on Microsoft.Extensions.Caching.Memory (>= 9.0.0) but version Microsoft.Extensions.Caching.Memory 8.0.1 was resolved. Approve the package to suppress this warning.
error NU1605: Detected package downgrade: Microsoft.Extensions.Logging from 9.0.0 to 8.0.1. Reference the package directly from the project to select a different version.
诊断:
  1. NU1101:包ID不存在,检查拼写、验证包源配置、确认包是否已重命名或弃用。
  2. NU1603:传递依赖版本冲突,某个包需要的版本高于已解析的版本。
  3. NU1605:检测到显式降级,两个包对同一依赖要求不同版本。
修复方案:
  • NU1101:修正包名称,在nuget.org搜索正确的包ID。
  • NU1603/NU1605:为冲突包添加直接
    <PackageReference>
    并指定兼容版本,或使用中央包管理固定版本。

IDE -- IDE/Roslyn Analyzer Code Style Diagnostics

IDE — IDE/Roslyn分析器代码样式诊断

Produced by Roslyn IDE analyzers for code style enforcement. These are usually warnings, not errors (unless
.editorconfig
escalates them).
Example output:
src/MyApp.Api/Program.cs(1,1): warning IDE0005: Using directive is unnecessary.
src/MyApp.Api/Models/Order.cs(8,12): warning IDE0044: Make field readonly
src/MyApp.Api/Services/Report.cs(22,5): warning IDE0058: Expression value is never used
Diagnosis:
  1. IDE0005: Unused
    using
    directive. Safe to remove.
  2. IDE0044: Field can be
    readonly
    because it is only assigned in the constructor.
  3. IDE0058: A method return value is discarded. Either assign it or use
    _ = ...
    to explicitly discard.
Fix pattern:
  • IDE analyzers enforce code style. Fix them by applying the suggested change. Configure severity in
    .editorconfig
    to promote warnings to errors for CI enforcement.
由Roslyn IDE分析器生成,用于强制执行代码样式,通常为警告(除非
.editorconfig
将其升级为错误)。
示例输出:
src/MyApp.Api/Program.cs(1,1): warning IDE0005: Using directive is unnecessary.
src/MyApp.Api/Models/Order.cs(8,12): warning IDE0044: Make field readonly
src/MyApp.Api/Services/Report.cs(22,5): warning IDE0058: Expression value is never used
诊断:
  1. IDE0005:存在未使用的
    using
    指令,可安全删除。
  2. IDE0044:字段可设为
    readonly
    ,因为仅在构造函数中赋值。
  3. IDE0058:方法返回值被丢弃,需将其赋值或使用
    _ = ...
    显式丢弃。
修复方案:
  • IDE分析器用于强制执行代码样式,按照建议修改代码即可。可在
    .editorconfig
    中配置严重级别,在CI中强制将警告升级为错误。

CA -- .NET Code Analysis (FxCop/Microsoft.CodeAnalysis.NetAnalyzers)

CA — .NET代码分析(FxCop/Microsoft.CodeAnalysis.NetAnalyzers)

Produced by the .NET code analysis SDK analyzers for API design, performance, reliability, and security rules.
Example output:
src/MyApp.Api/Services/CacheService.cs(34,9): warning CA1848: Use the LoggerMessage delegates instead of calling 'LoggerExtensions.LogInformation(ILogger, string?, params object?[])'. Using LoggerMessage delegates provides better performance.
src/MyApp.Api/Controllers/UserController.cs(12,5): warning CA2007: Consider calling ConfigureAwait on the awaited task
src/MyApp.Api/Crypto/HashService.cs(8,9): warning CA5351: Do Not Use Broken Cryptographic Algorithms (MD5)
Diagnosis:
  1. CA1848: High-performance logging. Use
    [LoggerMessage]
    source generator attributes instead of string interpolation in log calls.
  2. CA2007:
    ConfigureAwait(false)
    guidance for library code. Not applicable to ASP.NET Core app code (no
    SynchronizationContext
    ).
  3. CA5351: Security-critical. MD5 is broken for cryptographic purposes. Switch to SHA-256 or SHA-512.
Fix pattern:
  • CA1xxx (design): Apply suggested API changes. These improve API consistency.
  • CA2xxx (reliability/performance): Fix per suggestion. CA2007 can be suppressed in ASP.NET Core apps via
    .editorconfig
    .
  • CA5xxx (security): Always fix. These flag real security vulnerabilities.

由.NET代码分析SDK分析器生成,涵盖API设计、性能、可靠性和安全规则。
示例输出:
src/MyApp.Api/Services/CacheService.cs(34,9): warning CA1848: Use the LoggerMessage delegates instead of calling 'LoggerExtensions.LogInformation(ILogger, string?, params object?[])'. Using LoggerMessage delegates provides better performance.
src/MyApp.Api/Controllers/UserController.cs(12,5): warning CA2007: Consider calling ConfigureAwait on the awaited task
src/MyApp.Api/Crypto/HashService.cs(8,9): warning CA5351: Do Not Use Broken Cryptographic Algorithms (MD5)
诊断:
  1. CA1848:高性能日志建议,使用
    [LoggerMessage]
    源生成器属性替代日志调用中的字符串插值。
  2. CA2007:针对库代码的
    ConfigureAwait(false)
    建议,不适用于ASP.NET Core应用代码(无
    SynchronizationContext
    )。
  3. CA5351:安全关键警告,MD5加密算法已被破解,需切换为SHA-256或SHA-512。
修复方案:
  • CA1xxx(设计类):按照建议修改API,提升API一致性。
  • CA2xxx(可靠性/性能类):按照建议修复,ASP.NET Core应用中可通过
    .editorconfig
    抑制CA2007警告。
  • CA5xxx(安全类):必须修复,此类警告标识真实的安全漏洞。

NuGet Restore Failures

NuGet还原失败

NuGet restore is the first build step. When it fails, no compilation occurs. These are the most common restore failure patterns.
NuGet还原是构建的第一步,还原失败则无法进行编译,以下是最常见的还原失败模式。

Pattern: Package Not Found

模式:找不到包

Example output:
  Determining projects to restore...
  Writing assets file to disk. Path: /src/MyApp.Api/obj/project.assets.json
/src/MyApp.Api/MyApp.Api.csproj : error NU1101: Unable to find package MyCompany.Shared.Models. No packages exist with this id in source(s): nuget.org
  Failed to restore /src/MyApp.Api/MyApp.Api.csproj (in 2.14 sec).
Diagnosis:
  1. Is the package ID spelled correctly? NuGet IDs are case-insensitive but must be exact.
  2. Is the package from a private feed? Check
    nuget.config
    for feed configuration. NuGet searches feeds hierarchically upward from the project directory.
  3. Is
    packageSourceMapping
    configured? If so, the package must be mapped to a source that contains it.
    MyCompany.*
    patterns take precedence over
    *
    wildcard.
Fix pattern:
bash
undefined
示例输出:
  Determining projects to restore...
  Writing assets file to disk. Path: /src/MyApp.Api/obj/project.assets.json
/src/MyApp.Api/MyApp.Api.csproj : error NU1101: Unable to find package MyCompany.Shared.Models. No packages exist with this id in source(s): nuget.org
  Failed to restore /src/MyApp.Api/MyApp.Api.csproj (in 2.14 sec).
诊断:
  1. 包ID拼写是否正确?NuGet ID不区分大小写但必须完全匹配。
  2. 包是否来自私有源?检查
    nuget.config
    中的源配置,NuGet会从项目目录向上逐层搜索配置文件。
  3. 是否配置了
    packageSourceMapping
    ?如果是,包必须映射到包含它的源,
    MyCompany.*
    模式优先级高于
    *
    通配符。
修复方案:
bash
undefined

Check configured sources

检查已配置的源

dotnet nuget list source
dotnet nuget list source

Check if nuget.config exists (searches upward from project dir)

检查nuget.config是否存在(从项目目录向上搜索)

ls nuget.config ../nuget.config ../../nuget.config 2>/dev/null

```xml
<!-- Add private feed to nuget.config -->
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
    <add key="MyCompany" value="https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json" />
  </packageSources>
  <packageSourceMapping>
    <packageSource key="nuget.org">
      <package pattern="*" />
    </packageSource>
    <packageSource key="MyCompany">
      <package pattern="MyCompany.*" />
    </packageSource>
  </packageSourceMapping>
</configuration>
ls nuget.config ../nuget.config ../../nuget.config 2>/dev/null

```xml
<!-- 向nuget.config添加私有源 -->
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
    <add key="MyCompany" value="https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json" />
  </packageSources>
  <packageSourceMapping>
    <packageSource key="nuget.org">
      <package pattern="*" />
    </packageSource>
    <packageSource key="MyCompany">
      <package pattern="MyCompany.*" />
    </packageSource>
  </packageSourceMapping>
</configuration>

Pattern: Version Conflict

模式:版本冲突

Example output:
error NU1107: Version conflict detected for Microsoft.Extensions.DependencyInjection.Abstractions.
  MyApp.Api -> Microsoft.EntityFrameworkCore 9.0.0 -> Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
  MyApp.Api -> Microsoft.Extensions.Hosting 8.0.1 -> Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.1)
Diagnosis:
  1. Two dependency chains require different major versions of the same package.
  2. Trace each chain to find which top-level package is pinned at an older version.
  3. The fix is usually upgrading the older top-level package.
Fix pattern:
xml
<!-- Upgrade the older top-level package to match -->
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<!-- Or add a direct reference to force a specific version -->
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
示例输出:
error NU1107: Version conflict detected for Microsoft.Extensions.DependencyInjection.Abstractions.
  MyApp.Api -> Microsoft.EntityFrameworkCore 9.0.0 -> Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
  MyApp.Api -> Microsoft.Extensions.Hosting 8.0.1 -> Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.1)
诊断:
  1. 两条依赖链对同一包要求不同的主版本。
  2. 追踪每条依赖链,找到固定在旧版本的顶级包。
  3. 修复方案通常是升级旧版本的顶级包。
修复方案:
xml
<!-- 升级旧版本的顶级包以匹配版本 -->
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<!-- 或添加直接引用以强制指定版本 -->
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />

Pattern: Authentication Failure on Private Feed

模式:私有源认证失败

Example output:
  Retrying 'FindPackagesByIdAsyncCore' for source 'https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json'.
  Response status code does not indicate success: 401 (Unauthorized).
error NU1301: Unable to load the service index for source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json.
Diagnosis:
  1. Credentials are missing or expired for the private feed.
  2. In CI, check that the credential provider or PAT is configured.
  3. Locally, run
    dotnet nuget update source
    with credentials or use Azure Artifacts Credential Provider.
Fix pattern:
bash
undefined
示例输出:
  Retrying 'FindPackagesByIdAsyncCore' for source 'https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json'.
  Response status code does not indicate success: 401 (Unauthorized).
error NU1301: Unable to load the service index for source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json.
诊断:
  1. 私有源的凭据缺失或过期。
  2. 在CI环境中,检查凭据提供程序或PAT是否已配置。
  3. 在本地环境中,运行
    dotnet nuget update source
    添加凭据,或使用Azure Artifacts凭据提供程序。
修复方案:
bash
undefined

Install Azure Artifacts Credential Provider (see official docs for platform-specific steps):

安装Azure Artifacts凭据提供程序(请参阅官方文档获取平台特定步骤):

macOS/Linux: sh -c "$(curl -fsSL https://aka.ms/install-artifacts-credprovider.sh)"

macOS/Linux: sh -c "$(curl -fsSL https://aka.ms/install-artifacts-credprovider.sh)"

Or add credentials explicitly to a specific source

或为特定源显式添加凭据

dotnet nuget update source MyCompany --username az --password $PAT --store-password-in-clear-text

---
dotnet nuget update source MyCompany --username az --password $PAT --store-password-in-clear-text

---

Analyzer Warning Interpretation

分析器警告解读

Analyzer warnings are produced by Roslyn analyzers bundled with the SDK or added via NuGet. Understanding when to fix vs. when to configure severity is critical.
分析器警告由SDK自带或通过NuGet添加的Roslyn分析器生成,理解何时修复、何时配置严重级别至关重要。

Example Output

示例输出

src/MyApp.Api/Controllers/OrdersController.cs(27,5): warning CA2007: Consider calling ConfigureAwait on the awaited task [/src/MyApp.Api/MyApp.Api.csproj]
src/MyApp.Api/Services/OrderService.cs(15,16): warning CA1062: In externally visible method 'OrderService.Process(string)', validate parameter 'input' is non-null before using it [/src/MyApp.Api/MyApp.Api.csproj]
src/MyApp.Api/Models/UserDto.cs(8,12): warning IDE0032: Use auto-implemented property [/src/MyApp.Api/MyApp.Api.csproj]
Diagnosis:
  1. Identify the prefix:
    CA
    = Code Analysis (.NET analyzers),
    IDE
    = IDE code style analyzers.
  2. Check severity: warnings don't break builds unless
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    is set.
  3. Determine if the rule applies to your project type (e.g., CA2007 is irrelevant in ASP.NET Core — no SynchronizationContext).
  4. Decide: fix the code, configure severity in
    .editorconfig
    , or suppress with documented justification.
Fix pattern:
  • Fix the code when the analyzer identifies a real issue (CA1062 — add null validation or use
    ArgumentNullException.ThrowIfNull
    ).
  • Configure severity in
    .editorconfig
    when the rule doesn't apply project-wide (see below).
  • Suppress inline only with documented justification (see "When Suppression Is Acceptable" below).
src/MyApp.Api/Controllers/OrdersController.cs(27,5): warning CA2007: Consider calling ConfigureAwait on the awaited task [/src/MyApp.Api/MyApp.Api.csproj]
src/MyApp.Api/Services/OrderService.cs(15,16): warning CA1062: In externally visible method 'OrderService.Process(string)', validate parameter 'input' is non-null before using it [/src/MyApp.Api/MyApp.Api.csproj]
src/MyApp.Api/Models/UserDto.cs(8,12): warning IDE0032: Use auto-implemented property [/src/MyApp.Api/MyApp.Api.csproj]
诊断:
  1. 识别前缀:
    CA
    =代码分析(.NET分析器),
    IDE
    =IDE代码样式分析器。
  2. 检查严重级别:警告不会中断构建,除非设置了
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
  3. 判断规则是否适用于你的项目类型(例如CA2007与ASP.NET Core无关——无
    SynchronizationContext
    )。
  4. 决策:修复代码、在
    .editorconfig
    中配置严重级别,或添加文档说明后抑制警告。
修复方案:
  • 修复代码:当分析器识别到真实问题时(例如CA1062——添加空验证或使用
    ArgumentNullException.ThrowIfNull
    )。
  • 配置严重级别:当规则不适用于整个项目时(见下文)。
  • 内联抑制:仅在添加文档说明的情况下接受(见下文「何时可抑制警告」)。

Severity Levels

严重级别

SeverityBuild ImpactAction
ErrorBuild failsMust fix before build succeeds
WarningBuild succeeds (unless
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
)
Fix or configure in
.editorconfig
SuggestionBuild succeeds; shown in IDEFix when practical
HiddenNot shown; available via code fixIgnore unless actively refactoring
严重级别构建影响操作
Error构建失败必须修复才能完成构建
Warning构建成功(除非设置
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
修复或在
.editorconfig
中配置
Suggestion构建成功;仅在IDE中显示可行时修复
Hidden不显示;可通过代码修复工具查看除非主动重构,否则忽略

Configuring Severity

配置严重级别

Use
.editorconfig
to control analyzer behavior across the project:
ini
undefined
使用
.editorconfig
控制整个项目的分析器行为:
ini
undefined

.editorconfig (place at solution root)

.editorconfig(放置在解决方案根目录)

[*.cs]
[*.cs]

Promote nullable warnings to errors (recommended)

将可为空警告升级为错误(推荐)

dotnet_diagnostic.CS8600.severity = error dotnet_diagnostic.CS8602.severity = error dotnet_diagnostic.CS8603.severity = error
dotnet_diagnostic.CS8600.severity = error dotnet_diagnostic.CS8602.severity = error dotnet_diagnostic.CS8603.severity = error

Suppress ConfigureAwait warning in ASP.NET Core apps (no SynchronizationContext)

在ASP.NET Core应用中抑制ConfigureAwait警告(无SynchronizationContext)

dotnet_diagnostic.CA2007.severity = none
dotnet_diagnostic.CA2007.severity = none

Promote security warnings to errors

将安全警告升级为错误

dotnet_diagnostic.CA5350.severity = error dotnet_diagnostic.CA5351.severity = error
undefined
dotnet_diagnostic.CA5350.severity = error dotnet_diagnostic.CA5351.severity = error
undefined

When Suppression Is Acceptable

何时可抑制警告

Suppression is acceptable ONLY when:
  1. The analyzer cannot understand the code's safety guarantee (e.g., a custom guard clause that ensures non-null).
  2. The rule does not apply to the project type (e.g., CA2007 in ASP.NET Core apps).
  3. A documented justification is provided.
csharp
// ACCEPTABLE: documented justification
[SuppressMessage("Reliability", "CA2007:ConfigureAwait",
    Justification = "ASP.NET Core has no SynchronizationContext")]
public async Task<Order> GetOrderAsync(int id, CancellationToken ct)
{
    return await _repo.GetByIdAsync(id, ct);
}

// NOT ACCEPTABLE: no justification, hides a real issue
#pragma warning disable CA1062
public void Process(string input) { }  // input could be null
#pragma warning restore CA1062

仅在以下情况可抑制警告:
  1. 分析器无法理解代码的安全保证(例如自定义守卫语句确保非空)。
  2. 规则不适用于项目类型(例如ASP.NET Core应用中的CA2007)。
  3. 提供了文档说明。
csharp
undefined

Multi-Targeting Build Output

可接受:包含文档说明

When a project targets multiple frameworks, MSBuild builds each TFM separately. Errors may appear for only one target.
[SuppressMessage("Reliability", "CA2007:ConfigureAwait", Justification = "ASP.NET Core无SynchronizationContext")] public async Task<Order> GetOrderAsync(int id, CancellationToken ct) { return await _repo.GetByIdAsync(id, ct); }

Example Output

不可接受:无说明,隐藏真实问题

  MyApp.Shared -> /src/MyApp.Shared/bin/Debug/net8.0/MyApp.Shared.dll
src/MyApp.Shared/Services/FeatureService.cs(18,30): error CS1061: 'FrozenDictionary<string, int>' does not contain a definition for 'GetAlternateLookup' [/src/MyApp.Shared/MyApp.Shared.csproj -> net8.0]
  MyApp.Shared -> /src/MyApp.Shared/bin/Debug/net9.0/MyApp.Shared.dll
Build succeeded for net9.0.

Build FAILED for net8.0.
Diagnosis:
  1. The error tag
    [...csproj -> net8.0]
    shows which TFM failed.
    net9.0
    succeeded.
  2. GetAlternateLookup
    was added in .NET 9. The code uses an API not available in .NET 8.
  3. The fix requires conditional compilation or an alternative API for the older TFM.
Fix pattern:
csharp
// Use preprocessor directives for TFM-specific code
#if NET9_0_OR_GREATER
    var lookup = frozenDict.GetAlternateLookup<ReadOnlySpan<char>>();
    return lookup.TryGetValue(key, out var value) ? value : default;
#else
    return frozenDict.TryGetValue(key.ToString(), out var value) ? value : default;
#endif
xml
<!-- Or constrain the feature to specific TFMs in the project file -->
<PropertyGroup>
  <TargetFrameworks>net8.0;net9.0</TargetFrameworks>
</PropertyGroup>

<!-- TFM-conditional package reference -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
  <PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
</ItemGroup>
#pragma warning disable CA1062 public void Process(string input) { } // input可能为null #pragma warning restore CA1062

---

Reading Multi-Target Output

多目标框架构建输出

Key patterns for identifying TFM-specific issues:
  • [ProjectPath -> TFM]
    suffix on every diagnostic line identifies the target.
  • Build succeeded for netX.0
    /
    Build FAILED for netX.0
    summary at the end.
  • Restore output shows all TFMs:
    Restored ... (net8.0, net9.0)
    .
  • Build output paths include the TFM:
    bin/Debug/net8.0/
    vs
    bin/Debug/net9.0/
    .

当项目目标为多个框架时,MSBuild会单独构建每个TFM,错误可能仅出现在其中一个目标框架中。

CI Drift: Works Locally, Fails in CI

示例输出

The most frustrating build failures are ones that pass locally but fail in CI. These are almost always caused by environmental differences.
  MyApp.Shared -> /src/MyApp.Shared/bin/Debug/net8.0/MyApp.Shared.dll
src/MyApp.Shared/Services/FeatureService.cs(18,30): error CS1061: 'FrozenDictionary<string, int>' does not contain a definition for 'GetAlternateLookup' [/src/MyApp.Shared/MyApp.Shared.csproj -> net8.0]
  MyApp.Shared -> /src/MyApp.Shared/bin/Debug/net9.0/MyApp.Shared.dll
Build succeeded for net9.0.

Build FAILED for net8.0.
诊断:
  1. 错误标签
    [...csproj -> net8.0]
    显示哪个TFM构建失败,
    net9.0
    构建成功。
  2. GetAlternateLookup
    是.NET 9新增的API,代码使用了.NET 8不支持的API。
  3. 修复方案需要条件编译或为旧版本TFM使用替代API。
修复方案:
csharp
// 使用预处理器指令编写TFM特定代码
#if NET9_0_OR_GREATER
    var lookup = frozenDict.GetAlternateLookup<ReadOnlySpan<char>>();
    return lookup.TryGetValue(key, out var value) ? value : default;
#else
    return frozenDict.TryGetValue(key.ToString(), out var value) ? value : default;
#endif
xml
<!-- 或在项目文件中限制特性仅适用于特定TFM -->
<PropertyGroup>
  <TargetFrameworks>net8.0;net9.0</TargetFrameworks>
</PropertyGroup>

<!-- TFM条件包引用 -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
  <PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
</ItemGroup>

Pattern: Different SDK Version

解读多目标框架输出

Example scenario:
Local:  dotnet --version -> 9.0.200
CI:     dotnet --version -> 9.0.100

Build error in CI:
error CS8652: The feature 'field keyword' is currently in Preview and *unsupported*.
Diagnosis:
  1. The local SDK (9.0.200) includes a language preview feature that the CI SDK (9.0.100) does not.
  2. A
    global.json
    file is either missing or not pinning the SDK version.
Fix pattern:
json
// global.json -- pin SDK version for consistent builds
{
  "sdk": {
    "version": "9.0.200",
    "rollForward": "latestPatch"
  }
}
识别TFM特定问题的关键模式:
  • 每个诊断行的
    [ProjectPath -> TFM]
    后缀标识目标框架。
  • 末尾的
    Build succeeded for netX.0
    /
    Build FAILED for netX.0
    汇总信息。
  • 还原输出显示所有TFM:
    Restored ... (net8.0, net9.0)
  • 构建输出路径包含TFM:
    bin/Debug/net8.0/
    bin/Debug/net9.0/

Pattern: Missing Workload in CI

CI构建差异:本地正常、CI失败

Example scenario:
CI error:
error NETSDK1147: To build this project, the following workloads must be installed: maui-android
Diagnosis:
  1. MAUI/Aspire/WASM workloads installed locally but not in the CI image.
  2. CI pipeline needs explicit workload install step.
Fix pattern:
yaml
undefined
最棘手的构建失败是本地正常但CI失败的情况,几乎都是由环境差异导致的。

GitHub Actions example

模式:SDK版本不同

  • name: Install .NET workloads run: dotnet workload install maui-android maui-ios
undefined
示例场景:
本地: dotnet --version -> 9.0.200
CI:     dotnet --version -> 9.0.100

CI构建错误:
error CS8652: The feature 'field keyword' is currently in Preview and *unsupported*.
诊断:
  1. 本地SDK(9.0.200)包含语言预览特性,但CI环境的SDK(9.0.100)不支持。
  2. 缺少
    global.json
    文件或未固定SDK版本。
修复方案:
json
// global.json -- 固定SDK版本以确保构建一致性
{
  "sdk": {
    "version": "9.0.200",
    "rollForward": "latestPatch"
  }
}

Pattern: Implicit NuGet Sources

模式:CI环境缺失工作负载

Example scenario:
Local restore succeeds (using cached packages).
CI error:
error NU1101: Unable to find package MyCompany.Internal.Lib.
Diagnosis:
  1. Local machine has the package in the global NuGet cache from a previous restore.
  2. CI starts with a clean cache and cannot find the package because the private feed is not configured.
  3. A
    nuget.config
    file is missing from the repository, or CI lacks feed credentials.
Fix pattern:
  1. Add
    nuget.config
    to the repository root with all required package sources.
  2. Configure CI to authenticate to private feeds (credential provider, PAT, or managed identity).
  3. Do NOT rely on global NuGet cache for CI builds.
示例场景:
CI错误:
error NETSDK1147: To build this project, the following workloads must be installed: maui-android
诊断:
  1. 本地安装了MAUI/Aspire/WASM工作负载,但CI镜像中未安装。
  2. CI流水线需要显式的工作负载安装步骤。
修复方案:
yaml
undefined

Pattern: OS-Specific Path Differences

GitHub Actions示例

Example scenario:
Local (Windows):  Build succeeds
CI (Linux):       error MSB4018: The "ResolveAssemblyReference" task failed.
                  Could not find file '/src/MyApp/../Shared/MyLib.dll'
Diagnosis:
  1. Windows file system is case-insensitive; Linux is case-sensitive.
  2. A file reference uses different casing than the actual file on disk.
  3. Or backslash path separators in MSBuild properties that Linux cannot resolve.
Fix pattern:
  • Ensure file and directory names match the case used in project references exactly.
  • Use forward slashes (
    /
    ) in
    .csproj
    paths -- MSBuild normalizes them on all platforms.
  • Test in a Linux container locally with
    docker run
    before pushing.
  • name: Install .NET workloads run: dotnet workload install maui-android maui-ios
undefined

Pattern: TreatWarningsAsErrors in CI Only

模式:隐式NuGet源

Example scenario:
Local: Build succeeds with 3 warnings
CI:    error CS8602: Dereference of a possibly null reference.
       (because CI sets TreatWarningsAsErrors=true)
Diagnosis:
  1. CI pipeline or
    Directory.Build.props
    enables
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    via a CI-only condition.
  2. Developers see warnings locally but never fix them because the build succeeds.
Fix pattern:
  • Enable
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    unconditionally in
    Directory.Build.props
    so local and CI builds behave identically.
  • Fix all warnings. Do NOT add CI-only MSBuild properties that diverge from local behavior.

示例场景:
本地还原成功(使用缓存包)。
CI错误:
error NU1101: Unable to find package MyCompany.Internal.Lib.
诊断:
  1. 本地机器的全局NuGet缓存中存在该包,来自之前的还原操作。
  2. CI环境从干净缓存开始,因未配置私有源而找不到包。
  3. 仓库中缺少
    nuget.config
    文件,或CI环境缺少源凭据。
修复方案:
  1. 在仓库根目录添加包含所有所需包源的
    nuget.config
  2. 配置CI环境以认证私有源(凭据提供程序、PAT或托管标识)。
  3. CI构建请勿依赖全局NuGet缓存。

Slopwatch Anti-Patterns

模式:路径差异导致的OS兼容性问题

These patterns indicate an agent is hiding build problems rather than fixing them. Flag these during code review. See [skill:dotnet-slopwatch] for the automated quality gate that detects these patterns.
示例场景:
本地(Windows):构建成功
CI(Linux):       error MSB4018: The "ResolveAssemblyReference" task failed.
                  Could not find file '/src/MyApp/../Shared/MyLib.dll'
诊断:
  1. Windows文件系统不区分大小写,而Linux区分大小写。
  2. 文件引用使用的大小写与磁盘上的实际文件不一致。
  3. 或MSBuild属性中使用了反斜杠路径分隔符,Linux无法解析。
修复方案:
  • 确保文件和目录名称与项目引用中使用的大小写完全匹配。
  • .csproj
    中使用正斜杠(
    /
    )作为路径分隔符——MSBuild会在所有平台上自动规范化。
  • 推送前使用
    docker run
    在Linux容器中本地测试。

Warning Suppressions

模式:仅CI环境启用「将警告视为错误」

xml
<!-- RED FLAG: blanket NoWarn in .csproj -->
<PropertyGroup>
  <NoWarn>CS8600;CS8602;CS8603;CS8604;IL2026;IL2046</NoWarn>
</PropertyGroup>
csharp
// RED FLAG: pragma disable without justification
#pragma warning disable CS8618
public class UserModel
{
    public string Name { get; set; } // non-nullable not initialized
    public string Email { get; set; }
}
#pragma warning restore CS8618
Fix: Remove
<NoWarn>
entries and fix the underlying issues. If suppression is truly needed, use
.editorconfig
with per-rule severity and a comment explaining why.
示例场景:
本地:构建成功,出现3个警告
CI:    error CS8602: Dereference of a possibly null reference.
       (因为CI设置了TreatWarningsAsErrors=true)
诊断:
  1. CI流水线或
    Directory.Build.props
    通过CI专属条件启用了
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
  2. 开发者在本地仅看到警告,但因构建成功而未修复。
修复方案:
  • Directory.Build.props
    中无条件启用
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    ,使本地和CI构建行为一致。
  • 修复所有警告,请勿添加与本地行为不一致的CI专属MSBuild属性。

Silenced Analyzers Without Justification

不良模式(Slopwatch Anti-Patterns)

csharp
// RED FLAG: suppressing security analyzer with no explanation
[SuppressMessage("Security", "CA5351")]
public byte[] HashData(byte[] input)
{
    using var md5 = MD5.Create(); // insecure algorithm
    return md5.ComputeHash(input);
}
ini
undefined
这些模式表明Agent在隐藏构建问题而非修复问题,代码评审时需标记此类问题。请参考[skill:dotnet-slopwatch]了解检测这些模式的自动化质量门。

RED FLAG: disabling entire analyzer categories in .editorconfig

警告抑制

[*.cs] dotnet_diagnostic.CA5350.severity = none dotnet_diagnostic.CA5351.severity = none dotnet_diagnostic.CA5358.severity = none

**Fix:** Replace insecure algorithms (MD5 -> SHA-256). If suppression is unavoidable (e.g., interop with a system requiring MD5), add a `Justification` string explaining the constraint.

---
xml
<!-- 危险信号:在.csproj中批量禁用警告 -->
<PropertyGroup>
  <NoWarn>CS8600;CS8602;CS8603;CS8604;IL2026;IL2046</NoWarn>
</PropertyGroup>
csharp
// 危险信号:无说明的#pragma禁用
#pragma warning disable CS8618
public class UserModel
{
    public string Name { get; set; } // 非空属性未初始化
    public string Email { get; set; }
}
#pragma warning restore CS8618
修复: 删除
<NoWarn>
条目并修复根本问题。如果确实需要抑制警告,请在
.editorconfig
中配置每个规则的严重级别并添加说明。

Cross-References

无说明的分析器禁用

  • [skill:dotnet-agent-gotchas] -- common agent coding mistakes that produce build errors
  • [skill:dotnet-csproj-reading] -- project file structure, PropertyGroup/ItemGroup conventions
  • [skill:dotnet-project-structure] -- SDK selection, project organization, multi-project solutions
csharp
// 危险信号:无说明的安全分析器抑制
[SuppressMessage("Security", "CA5351")]
public byte[] HashData(byte[] input)
{
    using var md5 = MD5.Create(); // 不安全的算法
    return md5.ComputeHash(input);
}
ini
undefined

References

危险信号:在.editorconfig中禁用整个分析器类别

[*.cs] dotnet_diagnostic.CA5350.severity = none dotnet_diagnostic.CA5351.severity = none dotnet_diagnostic.CA5358.severity = none

**修复:** 替换不安全的算法(MD5 -> SHA-256)。如果确实无法避免抑制(例如与要求使用MD5的系统交互),请添加`Justification`字符串说明约束条件。

---

交叉参考

  • [skill:dotnet-agent-gotchas] — 导致构建错误的常见Agent编码错误
  • [skill:dotnet-csproj-reading] — 项目文件结构、PropertyGroup/ItemGroup约定
  • [skill:dotnet-project-structure] — SDK选择、项目组织、多项目解决方案

参考资料