Analyzers

Start with the official analyzers the .NET SDK, compiler, and editor already ship, then layer in C# Evolved guidance only as a follow-on.

The strongest analyzer story to promote first is the one developers already have: first-party guidance already catches API misuse, nudges teams toward modern C# syntax, and turns good practices into everyday feedback. Leading with those built-ins gives readers immediate value, lowers setup friction, and creates a cleaner baseline before C# Evolved introduces custom analyzers of its own.

Start here: turn on the official analyzer stack

Before adding custom analyzers, get the SDK, compiler, and Roslyn guidance you already have working for you. That is the fastest way to surface modern C# opportunities, API-quality issues, platform-compatibility warnings, and null-safety feedback without inventing a parallel process.

<PropertyGroup>
  <EnableNETAnalyzers>true</EnableNETAnalyzers>
  <AnalysisLevel>latest</AnalysisLevel>
  <AnalysisMode>Recommended</AnalysisMode>
  <CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
  <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
  <Nullable>enable</Nullable>
</PropertyGroup>
[*.cs]
dotnet_diagnostic.CA2000.severity = warning
dotnet_diagnostic.IDE0028.severity = warning
dotnet_diagnostic.CA1416.severity = warning
dotnet_diagnostic.CS8602.severity = warning

Official analyzer catalog

The cards below cover the official analyzer stories worth adopting first: activation and configuration, modern C# IDE suggestions, consistency-focused style rules, CA code-quality guidance, platform compatibility analysis, and nullable flow analysis.

.NET Team

Built-in SDK and Roslyn analyzer activation

.NET SDK + Roslyn Activation & Configuration Published

Lead with the analyzer stack that already ships in the .NET SDK, compiler, and Roslyn editor tooling so teams get actionable feedback in the editor, build output, and CI before adding anything custom.

The strongest analyzer story to promote first is the one developers already have: the SDK, compiler, and editor already ship first-party guidance for code quality, style, platform safety, and nullability.

  • Turn on EnableNETAnalyzers when a project does not already get the built-in CA rules by default.
  • Use AnalysisLevel, AnalysisMode, CodeAnalysisTreatWarningsAsErrors, and EnforceCodeStyleInBuild to decide how aggressively builds and CI enforce the official baseline.
  • Use Microsoft.CodeAnalysis.NetAnalyzers only when you need the official package-based path for older targets or a NuGet-driven update cadence.

Turn on: Use EnableNETAnalyzers, AnalysisLevel, AnalysisMode, CodeAnalysisTreatWarningsAsErrors, and EnforceCodeStyleInBuild in the project file, then set per-rule severities with dotnet_diagnostic.<ID>.severity in .editorconfig.

Example rules: CA1822, IDE0028, CS8602

Encourages: turn built-in analyzers on before adding custom ones, roll out severities deliberately across editor and CI

  • official
  • sdk
  • roslyn
  • editorconfig
  • build
.NET Team

Modern C# pattern suggestions

.NET SDK + Roslyn Modern C# Patterns Published

Official IDE analyzers suggest newer language patterns a little at a time, including collection expressions, pattern matching, using declarations, and primary constructors.

Official IDE rules make modern C# adoption incremental instead of disruptive: start with suggestions in the editor, then promote the patterns that help this codebase most.

// Before
public static class BeforeCollectionExpressionSample
{
    public static int[] CreateValues()
    {
        return new int[] { 1, 2, 3 };
    }
}

// After (C# 12+)
public static class AfterCollectionExpressionSample
{
    public static int[] CreateValues()
    {
        return [1, 2, 3];
    }
}

That same official style rule family also covers pattern matching (IDE0019), using declarations (IDE0063), and primary constructors (IDE0290) through .editorconfig options and per-rule severities.

Turn on: Configure style options in .editorconfig, turn on EnforceCodeStyleInBuild when you want build-time enforcement, and promote individual IDE rules with dotnet_diagnostic.<ID>.severity.

Example rules: IDE0028, IDE0019, IDE0063, IDE0290

Encourages: collection expressions, pattern matching, using declarations, primary constructors

  • official
  • csharp
  • ide
  • modernization
  • collection-expressions
  • pattern-matching
  • using-declarations
  • primary-constructors
.NET Team

Style, cleanup, and consistency guidance

.NET SDK + Roslyn Style & Consistency Published

Official style rules keep null checks, namespace shape, and other everyday cleanup choices consistent so broader modernization stays readable.

Consistency-focused IDE rules keep cleanup passes predictable, especially when the team is modernizing syntax in small batches instead of one disruptive rewrite.

// Before
public static class BeforeCustomerGuards
{
    public static bool IsMissing(object? customer)
    {
        return object.ReferenceEquals(customer, null);
    }
}

// After
public static class AfterCustomerGuards
{
    public static bool IsMissing(object? customer)
    {
        return customer is null;
    }
}

The same configuration story also covers file-scoped namespaces (IDE0161, C# 10+) so formatting and structure stay aligned across the repo.

Turn on: Keep the preferred style options in .editorconfig, use EnforceCodeStyleInBuild for build enforcement, and raise or lower individual IDE severities as the repo settles on conventions.

Example rules: IDE0041, IDE0161

Encourages: is null checks, file-scoped namespaces, repeatable cleanup passes

  • official
  • style
  • cleanup
  • consistency
  • file-scoped-namespaces
  • null-checks
.NET Team

API usage and code-quality guidance

.NET SDK + Roslyn Code Quality & API Usage Published

The SDK's CA analyzers bring performance, reliability, security, and API-usage guidance into normal compilation so issues surface before review.

The CA analyzer families move reliability, performance, security, and API-usage guidance into the build so reviewers do not have to rediscover the same issues by hand.

// Before
public sealed class BeforeNameFormatter
{
    public string Normalize(string value) => value.Trim();
}

// After
public sealed class AfterNameFormatter
{
    public static string Normalize(string value) => value.Trim();
}

That is only one example: the same official set also flags missed disposal paths (CA2000) and weak cryptography choices (CA5350).

Turn on: Keep EnableNETAnalyzers on, choose AnalysisLevel and AnalysisMode for the rollout you want, and use CodeAnalysisTreatWarningsAsErrors plus per-rule severities to decide what CI blocks.

Example rules: CA1822, CA2000, CA5350

Encourages: safer framework usage, deterministic disposal, stronger cryptography choices

  • official
  • code-quality
  • api
  • performance
  • reliability
  • security
.NET Team

Platform compatibility guidance

.NET SDK + Roslyn Platform Compatibility Published

CA1416 and related platform analysis help teams adopt platform-specific APIs safely by requiring target-framework context, attributes, or runtime guards.

Platform compatibility analysis deserves its own callout because it teaches safer use of OS-specific APIs instead of leaving those rules to tribal knowledge.

using Microsoft.Win32;

// Before
public static class BeforePlatformSamples
{
    public static object? ReadInstallPath()
    {
        return Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Contoso", "InstallPath", null);
    }
}

// After
public static class AfterPlatformSamples
{
    public static object? ReadInstallPath()
    {
        if (!System.OperatingSystem.IsWindows())
        {
            return null;
        }

        return Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Contoso", "InstallPath", null);
    }
}

CA1416 is the official rule to watch here, backed by target-framework context, platform attributes, and runtime guards.

Turn on: The platform analyzer rides with the official analyzer stack; for older targets you can set AnalysisLevel and dotnet_code_quality.enable_platform_analyzer_on_pre_net5_target, then tune dotnet_diagnostic.CA1416.severity.

Example rules: CA1416

Encourages: OperatingSystem guards, SupportedOSPlatform attributes, safer cross-platform APIs

  • official
  • platform
  • os-guards
  • ca1416
  • interoperability
.NET Team

Nullable and flow-analysis guidance

C# compiler + .NET SDK Nullable & Flow Analysis Published

Compiler nullability analysis keeps API contracts honest by warning on maybe-null dereferences and missing initialization before objects escape construction.

Nullable analysis is compiler-backed static analysis rather than a separate analyzer package, but it belongs in the same official-first rollout because it hardens API contracts early.

// Before
public static class BeforeTextSamples
{
    public static int LengthOrZero(string? value)
    {
        return value.Length;
    }
}

// After
public static class AfterTextSamples
{
    public static int LengthOrZero(string? value)
    {
        return value is null ? 0 : value.Length;
    }
}

That same nullable story also includes constructor and property initialization guidance such as CS8618 once <Nullable>enable</Nullable> is part of the project baseline.

Turn on: Enable nullable analysis with Nullable in the project file, then use nullable annotations, attributes, and per-warning severity choices to tighten the rollout over time.

Example rules: CS8602, CS8618

Encourages: explicit nullability, guarded dereferences, initialized non-null state

  • official
  • nullable
  • null-safety
  • flow-analysis
  • annotations
  • compiler

Coming from C# Evolved (in progress)

Our analyzers stay clearly secondary: use the official analyzer stack first, then add site-specific coaching when the local-only package preview is ready.

CSharpEvolved.Analyzers is still coming soon and local-only for now. It is meant to complement the .NET team's shipped analyzers with deeper links back to the teaching content on this site, not replace the official baseline.

Preview: what that complementary guidance looks like

CSE001 keeps the original example from this page because it shows the role C# Evolved should play well: spot a targeted modernization opportunity, offer a quick fix, and send the developer to the matching feature guide for the bigger picture.

public static class BeforeInterpolationSample
{
    public static string BuildMessage()
    {
        string name = "Mia";
        int count = 3;
        return string.Format("Hello, {0}! You have {1} messages.", name, count);
    }
}

public static class AfterInterpolationSample
{
    public static string BuildMessage()
    {
        string name = "Mia";
        int count = 3;
        return $"Hello, {name}! You have {count} messages.";
    }
}

The future diagnostic links directly to the string interpolation guide so the fix stays connected to the broader language story.

C# Evolved

CSE001 — Prefer string interpolation

C# Evolved C# Evolved follow-on Coming soon

Planned follow-on analyzer that spots string.Format-style code and points developers to the site's string interpolation guidance.

Planned C# Evolved analyzer that layers feature-teaching onto a familiar modernization nudge. The goal is not just to offer a fix, but to link that fix back to the site’s interpolation guide so teams understand when and why the newer syntax helps.

Rule: CSE001

Delivery: Coming soon as a local-only package preview after a repo build; not published to NuGet.

Encourages: interpolated strings, clearer inline formatting

  • string-interpolation
  • refactoring
  • docs-linked
C# Evolved

CSE002 — Prefer using declarations

C# Evolved C# Evolved follow-on Coming soon

Planned follow-on analyzer that nudges disposable-scope boilerplate toward using declarations and then links back to the site's feature guide.

Planned C# Evolved analyzer that complements the official analyzer story with a focused doc-backed suggestion for flatter disposal scopes. It is meant to turn a small cleanup into a teaching moment tied directly to the feature guide.

Rule: CSE002

Delivery: Coming soon as a local-only package preview after a repo build; not published to NuGet.

Encourages: using declarations, flatter disposal scopes

  • using-declarations
  • resource-management
  • docs-linked
C# Evolved

CSE003 — Prefer collection expressions

C# Evolved C# Evolved follow-on Coming soon

Planned follow-on analyzer that highlights older collection initializer shapes and points to collection expressions when the target code is ready.

Planned C# Evolved analyzer that connects collection-modernization hints to the site’s walkthrough of collection expressions. It stays intentionally complementary: use the built-in analyzer stack first, then add site-specific coaching where it helps most.

Rule: CSE003

Delivery: Coming soon as a local-only package preview after a repo build; not published to NuGet.

Encourages: collection expressions, more concise collection creation

  • collection-expressions
  • modernization
  • docs-linked

Local-only preview install

The package is not published to NuGet. Keep it framed as a local preview until the project explicitly says otherwise.

<!-- In your .csproj -->
<ItemGroup>
  <PackageReference Include="CSharpEvolved.Analyzers" Version="1.0.0">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
  </PackageReference>
</ItemGroup>

To restore from a local build, add the output directory as a NuGet source in nuget.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="Local" value="./analyzers/CSharpEvolved.Analyzers/bin/Release" />
  </packageSources>
</configuration>

Severity tuning for the future C# Evolved package

When the local-only preview is in play, keep the diagnostics as opt-in nudges or promote them one by one in .editorconfig:

[*.cs]
# Promote to warning if you want CI to enforce these
dotnet_diagnostic.CSE001.severity = warning
dotnet_diagnostic.CSE002.severity = warning
dotnet_diagnostic.CSE003.severity = warning

# Or suppress ones you're not ready for yet
dotnet_diagnostic.CSE003.severity = none

That keeps the official SDK and Roslyn analyzers as the baseline while the C# Evolved package remains an additive layer.