Code analysis configuration for .NET

September 20th 2024 Static Analysis .NET

The .NET SDK is accompanied by a large collection of code analysis rules, both for the C# language and for the SDK API usage. I firmly believe that for any long-lived project, it's worth the effort to configure the rules to match your preferences.

The default configuration is rather conservative so that it doesn't immediately overwhelm you with too many issues in the Visual Studio Error List window:

You can change both in the project properties window:

  • the compiler warning level in the Build Errors and warnings section Compiler warning level configuration
  • the code analysis level in the Code Analysis section Analysis level configuration

In the screenshots above I've enabled the highest level for both to be informed about as many potential issues as possible:

  • 9999 (All warnings) for compiler warning level
  • latest-all for code analysis level

I've also enabled the option to Treat warnings as errors which makes it impossible to ignore warnings because they cause the build to fail just like errors do.

For ASP.NET Core web API projects, it's common to generate the documentation file from the XML comments in code. This can be enabled in the Build Output section of project properties:

Enabling documentation file output

Having the XML documentation generated is required to include the method and property level documentation in the generated OpenAPI specification:

builder.Services.AddSwaggerGen(options =>
{
    var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
});

However, enabling the generation of the documentation file also enables warnings for all public types and members without XML documentation.

All the configuration settings described so far can of course also be set directly in the project file:

<PropertyGroup>
  <WarningLevel>9999</WarningLevel>
  <AnalysisLevel>latest-all</AnalysisLevel>
  <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
  <GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>

You can further customize the predefined sets of issues reported by code analysis. If it's just a single violation of a rule you want to ignore, you can suppress it:

Suppressing an issue in the code

This will add a #pragma directive directly in the source code:

return Enumerable
    .Range(1, 5)
    .Select(index => new WeatherForecast
    {
        Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
#pragma warning disable CA5394 // Do not use insecure randomness
        TemperatureC = Random.Shared.Next(-20, 55),
        Summary = Summaries[Random.Shared.Next(Summaries.Length)]
#pragma warning restore CA5394 // Do not use insecure randomness
    })
    .ToArray();

Alternatively, you can change the severity of a particular rule globally:

Globally configuring issue severity

This will add an entry to the .editorconfig file at the solution level (and create the file for you if you don't have one already)

[*.cs]

# CS1591: Missing XML comment for publicly visible type or member
dotnet_diagnostic.CS1591.severity = suggestion

I've pushed a sample project with all the configuration described here to my GitHub repository. You can check it out to see it all in place.

I've encountered too many .NET projects with tens or even hundreds of issues in their error list. I believe this is a bad idea as it will inevitably cause you to overlook any new warnings introduced in your code, no matter how serious they are. You have enough tools at your disposal to clear up that list in one way or another. Take the time to disable the issues you don't care about and fix those you do care about. And from that point forward handle any new issues as soon as they show up.

Get notified when a new blog post is published (usually every Friday):

Copyright
Creative Commons License