Modern C# Coding Standards
Intent
Enforce the use of modern C# (12+) features to improve code safety, readability, and performance. This includes a preference for immutability, functional-style patterns, and zero-allocation techniques.
When to Use
- Writing any new C# code (Records, Pattern matching, Primary constructors).
- Refactoring existing C# code to improve maintainability or performance.
- Designing domain models (Value Objects, Entities).
- Implementing high-performance or async-heavy paths.
Precondition Failure Signal
- Use of mutable classes where
recordorreadonly record structis appropriate. - Deep inheritance hierarchies instead of composition and interfaces.
- Manual null checks instead of Nullable Reference Types and pattern matching.
- Blocking on async code (
.Result,.Wait()) or missingCancellationToken. - Excessive allocations in performance-critical paths (not using
Span<T>).
Postcondition Success Signal
- Domain models use
record(DTOs/Entities) andreadonly record struct(Value Objects). - Code leverages
switchexpressions and modern pattern matching. Nullable Reference Typesare enabled and warnings addressed.- Async methods are "async all the way" and respect
CancellationToken. - High-performance paths use
Span<T>,Memory<T>, orArrayPool<T>.
Process
- Source Review: Inspect the code for outdated patterns (mutability, inheritance, blocking async).
- Implementation:
- Refactor to use modern C# features (e.g., convert class to record).
- Ensure all async calls are awaited and tokens passed.
- Use
Span<T>for buffer/string manipulation where performance is key.
- Verification:
- Run static analysis and linters to ensure compliance.
- Execute tests to verify behaviour remains unchanged.
- (Optional) Use benchmarks to demonstrate performance improvements for zero-allocation changes.
- Documentation: Document significant architectural patterns (e.g., Value Objects) in an ADR.
- Review: Tech Lead reviews for adherence to the "Modern C#" spirit.
Key Practices
- Use
recordandreadonly record structfor immutable domain modeling. - Prefer pattern matching over nested
if/elsebranches. - Pass
CancellationTokenthrough async call chains. - Use
Span<T>andMemory<T>for high-performance parsing and buffers.
Example Test / Validation
- Refactor: Convert a mutable DTO class to a positional
record. - Validation: Ensure
Nullableis enabled in.csprojand zero warnings exist. - Validation: Verify
CancellationTokenis passed to all downstream async calls.
Common Red Flags / Guardrail Violations
- "I'm used to the old way" (avoiding records/patterns).
- Ignoring nullable warnings by overusing
!. - Creating
BaseEntityorBaseServicehierarchies. - Using
AutoMapper(preferMapperlyfor compile-time safety).
Recommended Review Personas
- Tech Lead – validates modern pattern usage and architectural alignment.
- Software Engineer – validates implementation details and performance.
Skill Priority
P2 – Consistency & Governance
(Escalate to P1 for performance-critical or security-related code.)
Conflict Resolution Rules
- Modern C# standards override legacy patterns unless explicitly constrained by framework/interop requirements.
- Immutability is the default; mutability must be justified and scoped.
Conceptual Dependencies
- quality-gate-enforcement
- automated-standards-enforcement
Classification
Governance Core
Notes
See skills/modern-csharp-coding-standards/references/reference.md for focused examples and patterns.