Format and Code Analysis
|
This section documents MSBuild 18.9, the .NET SDK 10.0.402 (with its This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The C# Reference bibliography lists the reference material consulted while preparing these pages. |
Two tools keep C# code consistent: dotnet format, which rewrites files to match .editorconfig, and the
analyzers that run during every build and report CA (quality) and IDE (style) diagnostics. This page shows how
they are wired into the build and CI with .NET SDK 10.0.402. The style rules themselves, and how to choose them, are
in the C# Reference:
Coding
Conventions and Documentation — Analyzers and dotnet format.
dotnet format
dotnet format [<project|solution>] runs three passes, also available separately:
| Sub-command | What it fixes |
|---|---|
|
Indentation, spacing and new lines, from |
|
Code-style (IDE) rules with a severity in |
|
Fixable diagnostics of other analyzers (CA rules, third-party packages). |
--verify-no-changes reports instead of fixing; --diagnostics IDE0161 CA1305 and --severity warn|error|info
restrict what is considered; --include/--exclude restrict files.
Ledgerline's .editorconfig asks for file-scoped namespaces (csharp_style_namespace_declarations =
file_scoped:warning). A new file that ignores that and the indentation rules:
namespace Ledgerline.Cli
{
internal static class Formatting
{
public static string Amount(decimal value) => value.ToString("0.00");
}
}
dotnet build src/Ledgerline.Cli
dotnet format src/Ledgerline.Cli --verify-no-changes; echo "exit=$?"
0 Warning(s)
~/ledgerline/src/Ledgerline.Cli/Formatting.cs(5,7): error WHITESPACE: Fix whitespace formatting. Insert '\s\s'. [~/ledgerline/src/Ledgerline.Cli/Ledgerline.Cli.csproj]
~/ledgerline/src/Ledgerline.Cli/Formatting.cs(5,50): error WHITESPACE: Fix whitespace formatting. Delete 2 characters. [~/ledgerline/src/Ledgerline.Cli/Ledgerline.Cli.csproj]
~/ledgerline/src/Ledgerline.Cli/Formatting.cs(5,55): error WHITESPACE: Fix whitespace formatting. Delete 1 characters. [~/ledgerline/src/Ledgerline.Cli/Ledgerline.Cli.csproj]
~/ledgerline/src/Ledgerline.Cli/Formatting.cs(1,11): error IDE0161: Convert to file-scoped namespace [~/ledgerline/src/Ledgerline.Cli/Ledgerline.Cli.csproj]
exit=2
The build passed without a warning: IDE rules are not enforced in builds by default (next section).
dotnet format --verify-no-changes exits with 2 when files would change, which makes it a CI check. Fixing is the
same command without the flag, or one pass at a time:
dotnet format whitespace src/Ledgerline.Cli
dotnet format style src/Ledgerline.Cli
namespace Ledgerline.Cli;
internal static class Formatting
{
public static string Amount(decimal value) => value.ToString("0.00");
}
whitespace fixed the indentation and spacing; style converted the namespace. dotnet format needs a successful
restore (it loads the projects), and style/analyzers compile the code, so run it after dotnet restore in CI.
Source: dotnet format: Subcommands, whitespace, style, analyzers.
Analysis during the build
The .NET analyzers ship in the SDK and are on for projects targeting .NET 5 and later. Their configuration, queried on Ledgerline.Cli:
dotnet msbuild src/Ledgerline.Cli -getProperty:EnableNETAnalyzers -getProperty:AnalysisLevel \
-getProperty:AnalysisMode -getProperty:EnforceCodeStyleInBuild -getProperty:SdkAnalysisLevel \
-getProperty:EffectiveAnalysisLevel -getProperty:NoWarn
{
"Properties": {
"EnableNETAnalyzers": "true",
"AnalysisLevel": "latest",
"AnalysisMode": "",
"EnforceCodeStyleInBuild": "false",
"SdkAnalysisLevel": "10.0.400",
"EffectiveAnalysisLevel": "10.0",
"NoWarn": "1701;1702"
}
}
| Property | Meaning |
|---|---|
|
Run the CA analyzers (default |
|
Which release’s rule set and defaults: |
|
How many rules are on: |
|
Report IDE (style) rules with a severity during the build, not only in the editor. |
|
Escalate all warnings, escalate listed codes, suppress listed codes. |
|
Set to |
|
(.NET 9+) Make a newer SDK’s own tooling diagnostics behave as an older band’s — for example to delay new NuGet
or SDK warnings — without pinning the SDK. It defaults to the running SDK’s band ( |
Source: Code analysis overview: Enabled rules, Treat warnings as errors, Code style analysis: Enable on build, Configuration options: Analysis mode, Enable code analysis.
Enforcing style in the build
dotnet build src/Ledgerline.Cli --no-restore -p:EnforceCodeStyleInBuild=true
dotnet build src/Ledgerline.Cli --no-restore --no-incremental -p:EnforceCodeStyleInBuild=true
The first command reported nothing: the project had just been compiled, and changing this property on the command
line did not make the compiler target out of date, so it was skipped. The rebuild reported the rule — as an error,
because Ledgerline sets TreatWarningsAsErrors:
~/ledgerline/src/Ledgerline.Cli/Formatting.cs(1,11): error IDE0161: Convert to file-scoped namespace (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0161) [~/ledgerline/src/Ledgerline.Cli/Ledgerline.Cli.csproj]
Set EnforceCodeStyleInBuild in Directory.Build.props, where it is part of every build, rather than on one command
line. Some IDE rules (IDE0005, unnecessary usings) also need GenerateDocumentationFile to be reported in builds.
Turning more rules on
AnalysisMode=All on the CLI and its library (warnings kept as warnings for the experiment) reported four rules the
default mode leaves off:
dotnet build src/Ledgerline.Cli --no-restore --no-incremental -p:AnalysisMode=All -p:TreatWarningsAsErrors=false
2 warning CA1062
2 warning CA1305
2 warning CA1861
2 warning CA1869
(counts per rule, each reported twice by the console logger’s summary). Two of them, verbatim:
~/ledgerline/src/Ledgerline/Ledger.Json.cs(12,44): warning CA1869: Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead.
~/ledgerline/src/Ledgerline/LedgerReader.cs(15,20): warning CA1062: In externally visible method 'IReadOnlyList<JournalLine> LedgerReader.Parse(string csv)', validate parameter 'csv' is non-null before using it. If appropriate, throw an 'ArgumentNullException' when the argument is 'null'.
Each is a real finding for a library (CA1305 for culture-dependent formatting, CA1861 for a constant array allocated
per call). All is noisy for applications; Recommended is a common middle ground, with individual rules tuned in
.editorconfig.
In CI
dotnet restore --locked-mode
dotnet format --verify-no-changes --no-restore
dotnet build -c Release --no-restore
With EnforceCodeStyleInBuild and TreatWarningsAsErrors set in Directory.Build.props, the build alone fails on
style and quality rules; dotnet format --verify-no-changes adds the whitespace rules, which only the formatter checks.
Source: dotnet format.
Common mistakes
-
Expecting
.editorconfigseverities to fail the build — not withoutEnforceCodeStyleInBuild. -
Checking a property change with an incremental build — rebuild (
--no-incremental). -
AnalysisLevelleft atlatest— every SDK upgrade can add warnings; pin it (10.0) for warning-free upgrades. -
NoWarnin project files for rules that should be tuned — set severities in.editorconfig, where they are visible and per-folder. -
Running
dotnet formatbefore restore — it cannot load the projects.