Naming Conventions & Code Structure

Naming Standards

Private fields

Use _camelCase with a leading underscore (e.g., _userName) 

Constants

Use PascalCase without underscores (e.g., MaxRetryCount) 

Public properties

Use PascalCase (e.g., UserName) 

Local variables & parameters

Use camelCase (e.g., userId) 

Interfaces

Prefix with I using PascalCase (e.g., IUserRepository) 

Async methods

Suffix with Async (e.g., GetUserAsync) 

 

Order of content within the class

  1. Private readonly fields (top of class)
  2. Constants
  3. Constructors
  4. Public properties
  5. Public methods
  6. Protected methods
  7. Private methods
  8. Nested classes/structs (if any) 

 

Code Formatting 

  • Separate all methods with one blank line
  • Split constructor parameters one per line for improved readability
  • Use Ctrl + K + D to format code automaticallyMaintain consistent indentation (typically 4 spaces)
  • Remove unused usings via Ctrl + R + G 

Examples

Classes and methods

namespace EGFlow.Parser.Services 
{
    public class MyFoo
    {
        public Run(
            int index,
            string name
        )
        {
            // Do some fun things
            this.GetFoo(
                index,
                name
            );
        }

        private string GetFoo(
            int index,
            string name
        )
        {
            if (index > 1) {
                return "{index} - {name}";
            } else {
                return name;
            }           
        }
    }
}


Method calls within classes and services

// simple request
var foo = this.GetMyBar(parameter1);

// multiple parameter request (>2)
var foo = this.GetMyBar(
    parameter1,
    parameter2,
    parameter3
);


String Handling

  • Use string.Empty instead of ""
  • Use string.IsNullOrEmpty() for null or empty checks
  • Use string.IsNullOrWhiteSpace() for null, empty, or whitespace-only checks
  • Use string interpolation ($"{variable}") instead of concatenation for readability
  • Consider StringBuilder for extensive string manipulation in loops 

LINQ

  • Use .Count > 0 when you need the actual count
  • Use .Any() for existence checks (more performant)
  • Prefer Method syntax over Query syntax for consistency and readability
    • // Method syntax
      var activeUsers = users.Where(u => u.IsActive);
      
      // Query syntax
      var activeUsers = from u in users                  
      	where u.IsActive                  
      	select u;
  • Avoid multiple enumeration; materialize collections with .ToList() when needed
  • Use .FirstOrDefault() or .SingleOrDefault() appropriately based on expected results 

Async/Await

  • Always use async/await for I/O-bound operations (database, file, network)
  • Never use .Wait() or .Result to prevent deadlocks
  • Use ConfigureAwait(false) in library code to avoid context capture
  • Return Task or Task<T> for async methods (not async void except event handlers) 

 

Enum 

  • Use Enums in models instead of byte, int, or long for type safety
  • Avoid nullable enums in LINQ queries unless explicitly required
  • Define enums with explicit values 

 

Method & Parameter

  • Minimize method parameters (ideally ≤3-4 parameters)
  • Follow the Single Responsibility Principle (SRP)
  • Split large functions into smaller, focused methods
  • Use meaningful method names that describe intent (Follow ActionVerb pattern in the name
  • Use optional parameters or method overloading judiciously
  • Optional/default parameters should be stated last in the sequence of parameters.  - AVOID optional/default parameters if possible.  

 

Concurrency & Threading

  • Use locking mechanisms (lock, SemaphoreSlim) to prevent race conditions
  • Prefer async/await over explicit thread management
  • Use thread-safe collections (ConcurrentDictionary, ConcurrentQueue) when appropriate
  • Avoid shared mutable state where possible
  • Consider using Interlocked class for simple atomic operations 

 

Dependency Injection

  • Avoid creating objects via new inside methods; use DI container
  • Inject dependencies through constructors (constructor injection)
  • Register services with appropriate lifetimes
    • Transient: New instance per request
    • Scoped: Single instance per HTTP request/scope
    • Singleton: Single instance for application lifetime
    • Depend on interfaces/abstractions, not concrete implementations
    • Avoid service locator pattern; use explicit injection 

 

Exception Handling

  • Use specific exception types rather than generic Exception
  • Avoid catching exceptions you cannot handle meaningfully
  • Log exceptions with sufficient context for debugging
  • Use finally blocks or using statements for resource cleanup
  • Don't swallow exceptions silently without logging
  • Consider custom exception types for domain-specific errors 

 

Performance & Memory Management 

  • Dispose of resources properly using statements or IDisposable
  • Profile before optimizing; measure actual performance bottlenecks
  • Consider lazy initialization (Lazy<T>) for expensive object creation 

 

Code Quality & Maintainability 

  • Write XML documentation comments for public APIs
  • Follow DRY principle (Don't Repeat Yourself)
  • Use nullable reference types (C# 8.0+) to reduce null reference exceptions
  • Implement proper logging at appropriate levels (Debug, Info, Warning, Error)
  • Write unit tests with good coverage for critical business logic
    • Test driven development! Write tests as you go. 

 

Security Best Practices

  • Validate all inputs at API boundaries
  • Avoid exposing sensitive information in logs or error messages
  • Implement proper authentication and authorization
  • Use secure communication protocols (HTTPS, TLS)
  • Keep dependencies updated to patch security vulnerabilities 

 

API Design Best Practices

  • Follow RESTful conventions for HTTP APIs
  • Use appropriate HTTP status codes (200, 201, 400, 404, 500, etc.)
  • Version your APIs for backward compatibility
  • Implement proper error response models
  • Use DTOs (Data Transfer Objects) to separate API contracts from domain models
  • Document APIs using Swagger/OpenAPI 

 

  • No labels