C# Coding Guidelines

repository·main·Indexed 20 days ago

https://github.com/dennisdoomen/csharpguidelines

Comprehensive coding guidelines for C# (up to version 14), focusing on maintainability, simplicity, and SOLID principles. Includes class design standards (AV1000 series), documentation rules (AV2300), and idiomatic syntax recommendations. The repository provides tools to generate PDF documentation, a local Jekyll-based preview site, and integration options via CSharpGuidelinesAnalyzer, Roslyn analyzers, and AI skills.

Tokens
11.1K
Snippets
9
Records
55
Agent score
73%

What's inside csharpguidelines

  1. Testing scope and visibility (AV1605, AV1622)

    main

    To ensure tests remain resilient to refactoring, adhere to these visibility rules:

    • Public APIs Only (AV1605): Test observable behavior through public APIs only. Never attempt to test private methods or internal state directly.
    • Indirect Access (AV1622): If you need to verify internal implementation details, access them through the public API of the component that uses them, rather than accessing them directly.
  2. Core principles of the C# guidelines

    main

    The guidelines are built on several fundamental principles:

    • Deliberate Choice: The goal is to make deliberate coding choices and apply them consistently. Not all guidelines have a universal rationale; some are specific to Aviva Solutions.
    • Simplicity over Complexity: Regardless of how "elegant" a solution is, if it is too complex for an ordinary developer, exposes unusual behavior, or attempts to solve too many hypothetical future issues, it should be redesigned. Avoid the "But it works" anti-pattern.
    • General Guidelines: For code smells not explicitly covered in the specific C# sections, refer to the General Guidelines which apply across all contexts.
    • Generated Code: Generated code is exempt from these guidelines, though it is recommended to modify generation templates to comply as much as possible.
  3. Proper use of async/await and Task.Run (AV1820, AV1825)

    main

    To optimize performance and resource usage, follow these rules for asynchronous and parallel execution:

    • I/O-bound work: Use async/await for I/O-bound operations. Note that async/await does not automatically move code to a thread-pool thread; it is a mechanism for non-blocking waiting.
    • CPU-bound work: Use Task.Run to offload heavy computational work to a thread-pool thread.
    • Long-running operations: For background operations that persist for a long time, use TaskCreationOptions.LongRunning to hint to the scheduler that a dedicated thread may be required.
  4. Implement events using the OnXxx pattern (AV1225, AV1235)

    main

    To allow derived classes to intercept or suppress events, follow this pattern:

    1. Use protected virtual methods: Raise each event via a protected virtual OnXxx method (AV1225).
    2. Avoid null arguments: When raising an event, never pass null as the sender argument. If there are no event arguments to provide, pass EventArgs.Empty instead of null (AV1235).
  5. Use Interfaces for Decoupling and Extension (AV1004, AV1005, AV1008)

    main

    Use interfaces to create flexible and testable codebases:

    • Extension Points (AV1004): When designing for extensibility, expose extension points via interfaces rather than base classes.
    • Decoupling (AV1005): Use interfaces to decouple classes, prevent bidirectional associations, and facilitate Dependency Injection.
    • Static Classes (AV1008): Avoid using static classes for general logic as they are difficult to test and violate DI principles. The only exception is using static classes as containers for extension methods.
  6. Prefer idiomatic C# syntax over verbose .NET API calls

    main

    To write cleaner and more modern C# code, use idiomatic syntax instead of older, more verbose .NET API patterns. Recommended features include:

    • Tuple literals: For concise grouping of values.
    • Pattern matching: Use is null and is not null for null checks.
    • Null-coalescing assignment: Use ??= to assign values only if the variable is null.
    • Collection expressions: Use [] for concise collection initialization.
    • C# 14 features: Utilize the latest null-coalescing assignment improvements.