TFX50 C# & .NET 8+ Coding Standards
Enforce professional-grade coding standards for C# .NET 8+ projects with zero tolerance for security vulnerabilities, performance waste, or unclear code.
Objective
These are **mandatory directives**, not suggestions. Produce C# (.NET 8+) code that is, in priority order:
1. **Secure** - Impervious to common attacks
2. **Correct** - Free of bugs and logic flaws
3. **Performant** - Fast with minimal memory allocation (zero-allocation whenever possible)
4. **Clear** - Readable and self-explanatory without comments
5. **Consistent** - Uniform across the entire codebase
6. **Elegant** - Aesthetically pleasing and easy to navigate
7. **Maintainable** - Easy to modify and extend without introducing complexity
8. **Testable** - Easily covered by automated tests
9. **Scalable** - Designed to grow with the system
10. **Professional** - Reflects industry best practices
Naming Conventions
C# Types and Members
**Classes, Structs, Enums, Records**: `PascalCase` - Example: `UserService`, `OrderProcessor`, `CustomerStatus`
**Interfaces**: Prefix `I` followed by `PascalCase` - Example: `IRepository`, `IUserStore`, `IUnitOfWork`
**Methods and Properties**: `PascalCase` - Example: `GetByIdAsync`, `SaveChanges`, `LastAccessAt`, `IsValid`
**Private Fields**: Prefix `_` followed by `PascalCase` - Example: `_Cache`, `_Repository`, `_MaxSize`
**Static Private Fields**: Prefix `s_` followed by `PascalCase` - Example: `s_DefaultTimeout`, `s_ConnectionPool`
**Thread-Static Fields**: Prefix `t_` followed by `PascalCase` - Example: `t_CurrentContext`
**Method Parameters**: Prefix `p` followed by `PascalCase` - Example: `GetById(Guid pId)`, `UpdateUser(User pUser)`
**Local Variables**: `camelCase`, short and mnemonic - Example: `lstua` (list of active users), `frsrt` (first read table)
**Acronyms**: Keep uppercase when abbreviating (CEP, CPF, ID, URL, HTTP, JSON, XML, SQL, DB, UI, UX) - Example: `pUserID`, `GetByURL`, `LoadFromDB`
Code Style and Elegance
File Organization
**One Type Per File**: Mandatory. File name must match the primary type exactly.Code Structure
**No Braces for Single-Line Blocks**: `if`, `else`, `foreach`, `while`, `for` with single statements do NOT use braces ```csharp
if (pUser == null) return false;
```
**Early Returns (Guard Clauses)**: Mandatory. Validate conditions at method start and return immediately ```csharp
public bool ValidateUser(User pUser)
{
if (pUser == null) return false;
if (string.IsNullOrEmpty(pUser.Email)) return false;
// Main logic here
return true;
}
```
**No Comments**: Code must be self-explanatory. Need for comments indicates refactoring needed. - **Only Exception**: XML-Doc (`<summary>`) for public APIs describing "what", not "how"
**Avoid Anonymous Methods and Lambdas**: Critical rule. Avoid `Func<>`, `Action<>`, and lambda expressions (`=>`) in execution paths - Always prefer named methods (static or instance) for better readability, debugging, and reduced allocations
- **Exception**: Startup configuration (e.g., `Program.cs`) where readability is paramount and performance is non-critical
Quality and Design (SOLID + Immutability)
SOLID Principles (Non-Negotiable)
**S (Single Responsibility)**: Classes have one, and only one, reason to change**O (Open/Closed)**: Open for extension, closed for modification**L (Liskov Substitution)**: Derived types must be substitutable for base types**I (Interface Segregation)**: Create small, focused interfaces (`IUserReader`, `IUserWriter`) instead of monolithic ones**D (Dependency Inversion)**: Depend on abstractions (`IRepository`), not implementations (`SqlRepository`). Use DI extensivelyImmutability by Default
Use `record` for DTOs and value typesUse `readonly` on private fields whenever not modified after constructorExpose collections as `IReadOnlyCollection<T>` or `IEnumerable<T>`, never `List<T>`Extreme Performance (Zero-Allocation Mindset)
Be **obsessive** about memory allocations, especially in hot paths.
LINQ Restrictions
**No LINQ in Hot Paths**: Avoid `.Where()`, `.Select()`, `.ToList()` in frequently executed code**Reason**: LINQ allocates enumerators, delegates, and intermediate collections**Action**: Prefer explicit loops (`for`, `foreach`) for manual control and zero allocationAsync/Await Rules
Use `async/await` for all I/O operations (network, disk, database)**Never** use `async void` except for UI event handlers**Always** use `ConfigureAwait(false)` in library code to avoid deadlocksUse `ValueTask<T>` instead of `Task<T>` for methods that frequently complete synchronously (e.g., cache returns)Data Access (EF Core / Dapper)
**Always Use Projections**: Use `Select` to fetch only needed fields. Never `SELECT *`**Prevent N+1**: Use `Include()`, `ThenInclude()` or explicit projections**Don't Materialize Early**: Don't call `.ToList()` or `.ToArray()` until absolutely necessaryPerformance Optimizations
**Use Value Types (Structs)**: For small, immutable objects created in large quantities, prefer `readonly struct`**String Operations**: - Never concatenate strings in loops using `+`. Use `StringBuilder`
- For high-performance text processing, use `Span<T>` and `ReadOnlySpan<T>`
**Sealed Classes**: Mark classes as `sealed` if not designed for inheritance (helps JIT optimize)**`in` Parameters**: Use `in` modifier to pass large structs by reference without allowing modificationMandatory Security
Insecure code invalidates all other requirements.
Input Validation
**Never Trust User Input**: Validate all input at system boundaries (Controllers, API Endpoints)Use `FluentValidation` or model validationSQL Injection Prevention
**Zero Tolerance**: Always use parameterized queriesWith EF Core, this is defaultWith Dapper or ADO.NET, use `new { Id = pId }` or `SqlParameter`**Never** concatenate user input strings to form SQL queriesSecrets Management
**No Hardcoded Secrets**: Never hardcode connection strings, API keys, passwords, or tokensUse `IConfiguration` (from `appsettings.json`, environment variables) or secret vaults (Azure Key Vault, HashiCorp Vault)Authorization and Authentication
Apply `[Authorize]` (or equivalent permission check) to all non-anonymous endpointsDon't rely on frontend security checks. API must be secure independently**XSS Prevention**: Ensure data rendered in HTML/JS is properly encoded**Encryption**: Use modern .NET APIs (`System.Security.Cryptography`) for password hashing (with salt) and encrypting sensitive dataError Handling and Resilience
Exception Guidelines
**No Exceptions for Control Flow**: Exceptions are for exceptional cases onlyFor expected flows (e.g., "user not found"), use `Try*` pattern or return `null`/`*OrDefault`**Throw Specific Exceptions**: Don't throw `new Exception("Error")`. Use domain-specific exceptions or standard types (`ArgumentNullException`, `InvalidOperationException`)**Don't Suppress Errors**: Avoid empty `catch` blocks. Only catch if you can handle or add valuable contextResource Management
**Use `using` Declarations**: Ensure disposal of `IDisposable` resources ```csharp
using var context = _factory.CreateDbContext();
```
Testing Requirements
Test Design
Code must be easily testable with xUnit, NUnit, or MSTestDesign for deep testing including mocks and stubsDependencies should be injected to allow mockingMaximize test coverage through modular, decoupled designFinal Validation
Always perform build and validation before merging to main branchesExecute all automated tests before any final commitImplementation Checklist
When writing or reviewing code, verify:
1. **Naming**: `PascalCase`, `IInterface`, `_PrivatePascal`, `pParameterPascal`
2. **Style**: One type per file, no braces on single-line blocks, early returns
3. **No Noise**: No comments (except XML-Doc), no lambdas/anonymous methods in hot paths
4. **Design**: SOLID principles, DI, immutability (`record`, `readonly`)
5. **Performance**: `sealed` classes, `Span<T>`, `StringBuilder`, `ConfigureAwait(false)`
6. **SQL/EF**: No N+1, use projections, don't materialize early
7. **Security**: Validate all input, use SQL parameters, no hardcoded secrets
8. **Testing**: Code is modular, testable, and covered by automated tests
Example: Correct vs Incorrect
❌ Incorrect
```csharp
// Comment explaining what this does
public async Task<List<User>> GetActiveUsers()
{
var users = await context.Users.ToList(); // N+1 problem
return users.Where(u => u.IsActive).ToList(); // LINQ in hot path
}
```
✅ Correct
```csharp
public async Task<IReadOnlyCollection<UserDto>> GetActiveUsersAsync()
{
var lstau = new List<UserDto>();
var users = await _context.Users
.Where(u => u.IsActive)
.Select(u => new UserDto { Id = u.Id, Name = u.Name })
.ToListAsync()
.ConfigureAwait(false);
return users.AsReadOnly();
}
```
Notes
These standards are derived from the TFX50 project for DASE functionality demonstrationAll code must be in English (types, members, files)Consistency across the codebase is non-negotiableWhen in doubt, prioritize security and correctness over all else