See More

A very common reason is a wrong site baseUrl configuration.\n

Current configured baseUrl = / (default value)\n

We suggest trying baseUrl = \n\n',document.body.prepend(n);var e=document.getElementById("__docusaurus-base-url-issue-banner-suggestion-container"),s=window.location.pathname,o="/"===s.substr(-1)?s:s+"/";e.textContent=o}document.addEventListener("DOMContentLoaded",function(){void 0===window.docusaurus&&insertBanner()})

Skip to main content

Getting Started with ZeroAlloc.Analyzers

What is ZeroAlloc.Analyzers?

ZeroAlloc.Analyzers is a Roslyn analyzer NuGet package that detects allocation-heavy patterns in C# code and suggests zero or low-allocation alternatives. It covers 43 rules across 13 categories — from collection misuse and string concatenation to boxing, LINQ, async, and value type pitfalls. The package is multi-TFM aware: rules are automatically enabled or disabled based on the consuming project's <TargetFramework>, so you only see diagnostics that are actionable for your target runtime.


Installation

Add the package to your project via the .NET CLI:

dotnet add package ZeroAlloc.Analyzers

Or add the PackageReference directly in your .csproj file:

<PackageReference Include="ZeroAlloc.Analyzers" Version="*">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

The <PrivateAssets>all</PrivateAssets> setting ensures the analyzer is not propagated as a transitive dependency to consumers of your package — it stays a private development-time tool.


First Use

After installing the package, simply build your project:

dotnet build

Diagnostics are emitted during compilation and appear both in your IDE and in the MSBuild output. For example, you might see output like:

warning ZA0201: Avoid string concatenation in loops. Consider using a StringBuilder or interpolated string handler. [MyProject.csproj]
warning ZA0601: Avoid LINQ methods in hot-path loops. Consider caching the result outside the loop. [MyProject.csproj]
info ZA0107: Collection initialized without a known capacity. Consider pre-sizing with the expected element count. [MyProject.csproj]

Each diagnostic message includes the rule ID, a short description of the problem, and the file and line number where the issue was found. Rules with available code fixes also surface a suggested fix that can be applied directly from the IDE or via dotnet format.


IDE Setup

ZeroAlloc.Analyzers works automatically in all major C# IDEs — no additional configuration is required beyond installing the package.

  • Visual Studio 2022 — Diagnostics appear as squiggly underlines in the editor. Rules that have code fixes surface a lightbulb icon with one-click suggestions.
  • JetBrains Rider — Diagnostics are surfaced in the editor, the Errors & Warnings tool window, and the Inspection Results panel.
  • Visual Studio Code with C# Dev Kit — Diagnostics appear inline in the editor via the language server, and fixes are accessible through the quick-fix menu (Ctrl+.).

Because the analyzer ships as a standard Roslyn analyzer inside the NuGet package, any editor that supports the .NET language server (OmniSharp, Roslyn LSP) will surface diagnostics without additional setup.


TFM Awareness

Rules that rely on APIs introduced in specific .NET versions are automatically gated on the consuming project's <TargetFramework>. This means you will never see a diagnostic that suggests an API that does not exist in your target runtime.

For example:

  • ZA0101 (Use FrozenDictionary) only fires when targeting net8.0 or later, because FrozenDictionary<TKey, TValue> was introduced in .NET 8.
  • ZA0203 (Use AsSpan instead of Substring) only fires on net5.0+.
  • ZA0801 (Avoid Enum.HasFlag boxing) fires only when targeting frameworks below net7.0, where the JIT does not yet optimize the call.

For multi-targeting projects (<TargetFrameworks> plural), each TFM compilation is analyzed independently with the correct rule set for that target.

See configuration.md for details on how TFM gating works and how to override it.


Quick Suppression

If a diagnostic is not applicable to your codebase, you can suppress it in several ways.

Inline pragma

#pragma warning disable ZA0101
var lookup = new Dictionary<string, int>(data); // intentionally not frozen
#pragma warning restore ZA0101

Per-file or project-wide via .editorconfig

[*.cs]
dotnet_diagnostic.ZA0101.severity = none

To downgrade a warning to a suggestion:

dotnet_diagnostic.ZA0601.severity = suggestion

To promote an info diagnostic to a warning or error:

dotnet_diagnostic.ZA0107.severity = warning
dotnet_diagnostic.ZA0109.severity = error

See configuration.md for the full suppression and severity-tuning guide, including how to suppress categories of rules at once.


Rule Categories

ZeroAlloc.Analyzers organizes its 43 rules into 13 categories:


All Rules

The tables below list all 43 rules grouped by category. Rule IDs link to the corresponding section in each category's reference document. The Min TFM column shows the minimum target framework required for the rule to fire; Any means the rule applies to all supported frameworks.

Collections (ZA01xx)

Rule IDTitleSeverityMin TFM
ZA0101Use FrozenDictionary for read-only lookupsInfonet8.0
ZA0102Use FrozenSet for read-only membership testsInfonet8.0
ZA0103Use CollectionsMarshal.AsSpan for List iterationInfonet5.0
ZA0104Use SearchValues for repeated char/byte lookupsInfonet8.0
ZA0105Use TryGetValue instead of ContainsKey + indexerWarningAny
ZA0106Avoid premature ToList/ToArray before LINQWarningAny
ZA0107Pre-size collections when capacity is knownInfoAny
ZA0108Avoid redundant ToList/ToArray materializationWarningAny
ZA0109Avoid zero-length array allocationWarningAny

Strings (ZA02xx)

Rule IDTitleSeverityMin TFM
ZA0201Avoid string concatenation in loopsWarningAny
ZA0202Avoid chained string.Replace callsInfoAny
ZA0203Use AsSpan instead of SubstringInfonet5.0
ZA0204Use string.Create instead of string.FormatInfonet6.0
ZA0205Use CompositeFormat for repeated format stringsInfonet8.0
ZA0206Avoid span.ToString() before ParseInfonet6.0
ZA0208Avoid string.Join boxing overloadWarningAny
ZA0209Avoid value type boxing in string concatenationWarningAny

Memory (ZA03xx)

Rule IDTitleSeverityMin TFM
ZA0301Use stackalloc for small fixed-size buffersInfoAny
ZA0302Use ArrayPool for large temporary arraysInfoAny

Logging (ZA04xx)

Rule IDTitleSeverityMin TFM
ZA0401Use LoggerMessage source generatorInfonet6.0

Boxing (ZA05xx)

Rule IDTitleSeverityMin TFM
ZA0501Avoid boxing value types in loopsWarningAny
ZA0502Avoid closure allocations in loopsInfoAny
ZA0504Avoid defensive copies on readonly structsInfoAny

LINQ (ZA06xx)

Rule IDTitleSeverityMin TFM
ZA0601Avoid LINQ methods in loopsWarningAny
ZA0602Avoid params calls in loopsInfoAny
ZA0603Use .Count/.Length instead of LINQ .Count()InfoAny
ZA0604Use .Count > 0 instead of LINQ .Any()InfoAny
ZA0605Use indexer instead of LINQ .First()/.Last()InfoAny
ZA0606Avoid foreach over interface-typed collectionWarningAny
ZA0607Avoid multiple enumeration of IEnumerableWarningAny

Regex (ZA07xx)

Rule IDTitleSeverityMin TFM
ZA0701Use GeneratedRegex for compile-time regexInfonet7.0

Enums (ZA08xx)

Rule IDTitleSeverityMin TFM
ZA0801Avoid Enum.HasFlag (boxes on pre-net7.0)Info<net7.0
ZA0802Avoid Enum.ToString() allocationsInfoAny
ZA0803Cache Enum.GetName/GetValues in loopsInfoAny

Sealing (ZA09xx)

Rule IDTitleSeverityMin TFM
ZA0901Consider sealing classesInfoAny

Serialization (ZA10xx)

Rule IDTitleSeverityMin TFM
ZA1001Use JSON source generationInfonet7.0

Async (ZA11xx)

Rule IDTitleSeverityMin TFM
ZA1101Elide async/await on simple tail callsInfoAny
ZA1102Dispose CancellationTokenSourceInfoAny
ZA1104Avoid Span<T> in async methodsWarningAny

Delegates (ZA14xx)

Rule IDTitleSeverityMin TFM
ZA1401Use static lambda when no capture neededInfonet5.0

Value Types (ZA15xx)

Rule IDTitleSeverityMin TFM
ZA1501Override GetHashCode on struct keysInfoAny
ZA1502Avoid finalizers, use IDisposableInfoAny

Next Steps

  • Configuration guide — Customize severities, suppress rules, and understand TFM gating in depth.
  • Contributing — Learn how to add new rules, write tests, and submit pull requests.