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
- Private readonly fields (top of class)
- Constants
- Constructors
- Public properties
- Public methods
- Protected methods
- Private methods
- 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 automatically – Maintain consistent indentation (typically 4 spaces)
Remove unused usings via Ctrl + R + G
Examples:
Classes/methods:
namespace EGFlow.Parser.Services
{
public class Blah
{
public Blah(
string thing,
int anotherThing
)
{
}
public string DoSomething(
string something,
int anotherSomething
)
{
return "Hello";
}
}
}
- String Handling Best Practices
- 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 Best Practices
- 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
- Avoid multiple enumeration; materialize collections with .ToList() when needed
- Use .FirstOrDefault() or .SingleOrDefault() appropriately based on expected results
- Async/Await Best Practices
- 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 Best Practices
- 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 Best Practices
- 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 Best Practices
- 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 Best Practices
- 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 Best Practices
- 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