C# Static Code Analysis: A Developer's Guide
A practical guide to static code analysis for C# — Roslyn analyzers, SonarQube, Security Code Scan, and how to build a complete .NET analysis pipeline.
- 1.C# and Static Analysis
- 2.Key C# Static Analysis Tools
- 3.Common Issues Detected
- 4.Running Static Analysis
- 5.Nullable Reference Types
C# and Static Analysis
C# and the .NET platform have strong built-in static analysis support through the Roslyn compiler platform. Unlike many languages where analysis tools are separate from the compiler, Roslyn exposes the compiler's AST and semantic model as a public API — enabling analysis tools to operate with the same depth of understanding as the compiler itself.
This architectural advantage means C# analysis tools are highly accurate and deeply integrated into the development workflow through Visual Studio, Visual Studio Code, and Rider IDE plugins.
Key C# Static Analysis Tools
Roslyn Analyzers
The built-in .NET SDK includes the Microsoft.CodeAnalysis.NetAnalyzers package, which ships with hundreds of analysis rules covering code quality, security, and best practices. These are enabled by default in .NET 5+ projects. Rules cover: API design, globalization, interoperability, maintainability, naming, performance, reliability, security, and usage.
StyleCop Analyzers
Enforces StyleCop coding standards for C#: documentation, layout, maintainability, naming, ordering, readability, and spacing rules. Integrated as Roslyn analyzers, they run in the build pipeline without separate tooling.
SonarQube / SonarCloud
Comprehensive quality and security analysis with a dashboard view. SonarQube C# analysis detects hundreds of bug patterns, security vulnerabilities (including OWASP Top 10), and code smells. The SonarLint Visual Studio extension provides real-time analysis in the IDE.
Security Code Scan
Open-source Roslyn analyzer focused on security vulnerabilities in C# and VB.NET applications. Detects: SQL injection, XSS, path traversal, LDAP injection, CSRF, cryptographic weaknesses, and insecure deserialization. Particularly useful for ASP.NET and ASP.NET Core applications.
Roslynator
A large collection of Roslyn analyzers, refactorings, and fixes. Includes 500+ analyzers covering code quality, style, and simplifications. Many findings come with automatic code fixes.
Common Issues Detected
- SQL injection via string concatenation in SqlCommand or Dapper queries
- XSS via unencoded output in Razor templates
- Insecure deserialization via BinaryFormatter or JavaScriptSerializer
- Hardcoded credentials in connection strings and appsettings
- Cryptographic weaknesses: MD5, SHA1, DES usage
- CSRF protection issues in ASP.NET Core controllers
- Null reference exceptions (with nullable reference types analysis)
- Async/await misuse: async void, deadlocking patterns, ConfigureAwait
- IDisposable resources not properly disposed
Running Static Analysis
.NET CI analysis pipeline:
- dotnet build -- Roslyn analyzers run as part of compilation with <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- dotnet build /p:AnalysisMode=All -- enable all available analyzers
- dotnet tool run security-scan -- run Security Code Scan
- Connect to SonarQube: dotnet sonarscanner begin / build / end
- Configure <CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors> in project files to fail builds on analysis findings
Nullable Reference Types
C# 8.0 introduced nullable reference types — a compiler feature that distinguishes nullable references (string?) from non-nullable references (string). Enabling nullable analysis in the project file (<Nullable>enable</Nullable>) makes the compiler warn on potential null dereferences. This is one of the most impactful quality improvements available for C# codebases.
Connection to Autonomous Code Governance
Roslyn's rich code fix API means many C# static analysis findings come with suggested fixes built in. Hydra extends this by generating fixes for security findings that Roslyn identifies but doesn't automatically correct — SQL injection, deserialization vulnerabilities, cryptographic weaknesses — verifying them with unit tests and delivering convention-matched PRs that pass the full .NET analysis pipeline.
Frequently Asked Questions
What is Roslyn?
Roslyn is the open-source .NET compiler platform (C# and VB.NET compilers). Unlike traditional compilers that are black boxes, Roslyn exposes its AST, semantic model, and symbol tables as public APIs. This makes it possible to write analysis tools, refactoring tools, and code fixers that have the same depth of understanding as the compiler itself.
How do I enable .NET Roslyn analyzers?
In .NET 5+, Microsoft.CodeAnalysis.NetAnalyzers is included by default. Set <AnalysisMode>All</AnalysisMode> in your .csproj or Directory.Build.props to enable all available rules. Add <TreatWarningsAsErrors>true</TreatWarningsAsErrors> to fail builds on analysis findings.
What is nullable reference types analysis in C#?
Nullable reference types (enabled with <Nullable>enable</Nullable> in csproj) make the C# compiler track whether reference types can be null. string is non-nullable by default; string? is explicitly nullable. The compiler warns when you dereference a potentially null value without a null check. This eliminates most NullReferenceExceptions by catching them at compile time.
What is the difference between a Roslyn analyzer and a regular linter?
A regular linter typically analyzes text or a simplified parse tree. A Roslyn analyzer operates on the full semantic model — it knows the resolved type of every expression, the full call graph, and the symbol bindings. This allows Roslyn analyzers to detect issues that text-based linters cannot: for example, detecting that a specific method call will always throw because its contract cannot be satisfied given the surrounding types.
How do I suppress specific Roslyn analyzer warnings?
Use #pragma warning disable CS{code} / #pragma warning restore CS{code} for file-level suppression. Add [SuppressMessage("Category", "RuleId")] attributes for member-level suppression. Configure <NoWarn>CS{code}</NoWarn> in the csproj for project-level suppression. Always document why a warning is suppressed — unsuppressed suppressions are code smell.
Stop flagging. Start fixing.
Hyrax reviews your pull requests, remediates issues autonomously, and closes the ticket.
Join the waitlist