Bielu.StaticCode.Analyzers 1.0.0-beta.639111005801575032

Prefix Reserved
This is a prerelease version of Bielu.StaticCode.Analyzers.
dotnet add package Bielu.StaticCode.Analyzers --version 1.0.0-beta.639111005801575032
                    
NuGet\Install-Package Bielu.StaticCode.Analyzers -Version 1.0.0-beta.639111005801575032
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bielu.StaticCode.Analyzers" Version="1.0.0-beta.639111005801575032">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Bielu.StaticCode.Analyzers" Version="1.0.0-beta.639111005801575032" />
                    
Directory.Packages.props
<PackageReference Include="Bielu.StaticCode.Analyzers">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Bielu.StaticCode.Analyzers --version 1.0.0-beta.639111005801575032
                    
#r "nuget: Bielu.StaticCode.Analyzers, 1.0.0-beta.639111005801575032"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Bielu.StaticCode.Analyzers@1.0.0-beta.639111005801575032
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Bielu.StaticCode.Analyzers&version=1.0.0-beta.639111005801575032&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Bielu.StaticCode.Analyzers&version=1.0.0-beta.639111005801575032&prerelease
                    
Install as a Cake Tool

Bielu.StaticCode.Analyzers

NuGet

Roslyn-based static code analyzers that enforce coding conventions used across the bielu ecosystem.

Installation

<PackageReference Include="Bielu.StaticCode.Analyzers">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

Analyzers

Rule ID Category Severity Title
BIELU001 Naming Warning Decorator naming convention
BIELU002 Style Warning Use primary constructor
BIELU003 Usage Warning Use IOptionsMonitor<T>
BIELU004 Usage Warning Use ILogger<T>
BIELU005 Naming Warning Async method naming
BIELU006 Naming Warning IServiceCollection extension class naming
BIELU007 Style Warning Use ArgumentNullException.ThrowIfNull()
BIELU008 Usage Warning Use ConfigureAwait(false)
BIELU009 Design Info Seal internal classes

BIELU001 – Decorator Naming Convention

Decorator classes must follow the naming pattern {Modifier}{InterfaceName}Decorator.

❌ Incorrect ✅ Correct
ApiServiceCache : IApiService CachedApiServiceDecorator : IApiService
LoggingUserRepo : IUserRepository LoggedUserRepositoryDecorator : IUserRepository

A class is considered a decorator when it:

  1. Implements an interface that starts with I (e.g. IApiService)
  2. Has a constructor parameter of the same interface type

The class name must end with {InterfaceNameWithoutI}Decorator (e.g. ApiServiceDecorator), optionally prefixed by a modifier (e.g. Cached, Logged, Resilient).

BIELU002 – Use Primary Constructor

Classes with a single constructor whose body only contains simple field or property assignments should use the primary constructor syntax introduced in C# 12.

// ❌ Traditional constructor - can be simplified
public class MyService
{
    private readonly ILogger _logger;
    public MyService(ILogger logger) { _logger = logger; }
}

// ✅ Primary constructor
public class MyService(ILogger logger)
{
    private readonly ILogger _logger = logger;
}

Conditions under which the rule does not apply:

  • The class already uses a primary constructor
  • The class is abstract or static
  • The class has more than one constructor
  • The constructor chains to another constructor (base(...) / this(...))
  • The constructor body contains logic beyond simple assignments

BIELU003 – Use IOptionsMonitor<T>

Options should be injected using IOptionsMonitor<T> rather than IOptions<T> or IOptionsSnapshot<T>.

IOptionsMonitor<T> provides the current configuration value and supports change notifications, making it the preferred choice for hot-reload scenarios.

❌ Incorrect ✅ Correct
IOptions<MyOptions> IOptionsMonitor<MyOptions>
IOptionsSnapshot<MyOptions> IOptionsMonitor<MyOptions>

A code fix is provided to automatically replace IOptions<T> / IOptionsSnapshot<T> with IOptionsMonitor<T>.

BIELU004 – Use ILogger<T>

Constructor parameters should use the typed ILogger<T> (where T is the containing class) instead of the untyped ILogger interface. Typed loggers enable proper log categorization and filtering.

// ❌ Untyped logger
public class MyService(ILogger logger) { }

// ✅ Typed logger
public class MyService(ILogger<MyService> logger) { }

BIELU005 – Async Method Naming

Methods returning Task, Task<T>, ValueTask, or ValueTask<T> should have their name suffixed with Async.

// ❌ Missing Async suffix
public Task GetData() => Task.CompletedTask;

// ✅ Correct suffix
public Task GetDataAsync() => Task.CompletedTask;

Exceptions:

  • Overridden methods (naming is dictated by the base class)
  • Interface implementations (naming is dictated by the interface)
  • Test methods (marked with [Fact], [Theory], [Test], or [TestMethod])

BIELU006 – IServiceCollection Extension Class Naming

Static classes containing extension methods on IServiceCollection should be named {Feature}ServiceCollectionExtensions.

// ❌ Wrong name
public static class MyFeatureExtensions
{
    public static IServiceCollection AddMyFeature(this IServiceCollection services) => services;
}

// ✅ Correct name
public static class MyFeatureServiceCollectionExtensions
{
    public static IServiceCollection AddMyFeature(this IServiceCollection services) => services;
}

BIELU007 – Use ArgumentNullException.ThrowIfNull()

Null guard clauses should use the modern ArgumentNullException.ThrowIfNull() pattern instead of manual if (param == null) throw new ArgumentNullException(...).

// ❌ Manual null check
if (name == null)
    throw new ArgumentNullException(nameof(name));

// ✅ Modern guard clause
ArgumentNullException.ThrowIfNull(name);

BIELU008 – Use ConfigureAwait(false)

In library code, awaited tasks should call .ConfigureAwait(false) to avoid capturing the synchronization context, preventing potential deadlocks and improving performance.

// ❌ Missing ConfigureAwait
await Task.Delay(100);

// ✅ Explicit ConfigureAwait
await Task.Delay(100).ConfigureAwait(false);

BIELU009 – Seal Internal Classes

Internal classes that are not designed for inheritance should be marked as sealed. This prevents accidental inheritance, makes intent clear, and enables JIT devirtualization optimizations. This rule is reported as Info severity.

// ⚠️ Could be sealed
internal class MyHelper { }

// ✅ Sealed
internal sealed class MyHelper { }

Exceptions:

  • Classes that are already sealed, abstract, or static
  • Classes with virtual or abstract members
  • Classes that have derived classes in the same file

Contributing

See CONTRIBUTING.md for guidelines on contributing to this project.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-beta.639111005801575032 45 4/6/2026
1.0.0-beta.639111005608317015 34 4/6/2026
1.0.0-beta.639110666014511987 41 4/6/2026
1.0.0-beta.639110662170060676 38 4/6/2026
1.0.0-beta.639110661948474033 30 4/6/2026
1.0.0-beta.639110661625783281 33 4/6/2026
1.0.0-beta.639110661538243926 35 4/6/2026
1.0.0-beta.639110652434715608 49 4/6/2026