C# Clean Code
2026/03/223 min read
bookmark this
Introduction
Most readability issues in C# code come from two places:
- weak naming
- methods doing too many things
If you improve only these two areas, your code quality rises quickly.
1) Naming conventions that scale
Use intention-revealing names
A good name explains purpose without comments.
// BAD
int d; // elapsed days
// GOOD
int elapsedTimeInDays;
Follow C# casing conventions
PascalCase: classes, methods, properties, constantscamelCase: local variables, method parameters_camelCase: private fields
public class OrderService
{
private readonly IOrderRepository _orderRepository;
public async Task<Order?> GetOrderByIdAsync(int orderId, CancellationToken ct)
{
var order = await _orderRepository.GetByIdAsync(orderId, ct);
return order;
}
}
Prefer domain words over abbreviations
// BAD
var custMgr = new CM();
// GOOD
var customerManager = new CustomerManager();
Boolean names should read like questions
Good booleans: isActive, hasPermission, canExecute.
2) Method design principles
Keep methods small and single-purpose
If a method validates input, calculates data, writes to database, and sends email, it has multiple responsibilities.
public async Task ProcessOrderAsync(OrderRequest request, CancellationToken ct)
{
Validate(request);
decimal total = CalculateTotal(request.Items);
var order = await SaveOrderAsync(request.CustomerId, total, ct);
await NotifyCustomerAsync(order, ct);
}
Keep parameter count low
When a method needs many primitives, introduce a request object.
public record CreateUserRequest(
string FirstName,
string LastName,
string Email,
string Phone,
Address Address);
public Task CreateUserAsync(CreateUserRequest request, CancellationToken ct);
Avoid boolean flag arguments
// BAD
RenderPage(page, true);
// GOOD
RenderPageForPrinting(page);
RenderPageForScreen(page);
Use guard clauses to reduce nesting
// BAD
public decimal GetDiscount(Customer customer)
{
decimal discount = 0m;
if (customer != null)
{
if (customer.IsActive)
{
if (customer.OrderCount > 10)
{
discount = 0.15m;
}
else
{
discount = 0.05m;
}
}
}
return discount;
}
// GOOD
public decimal GetDiscount(Customer customer)
{
if (customer is null) return 0m;
if (!customer.IsActive) return 0m;
return customer.OrderCount > 10 ? 0.15m : 0.05m;
}
Avoid hidden side effects
Method names must match behavior.
// BAD
public bool CheckPassword(string password)
{
if (Encrypt(password) == _storedHash)
{
Session.Initialize(); // hidden side effect
return true;
}
return false;
}
// BETTER
public bool IsPasswordValid(string password) => Encrypt(password) == _storedHash;
public void InitializeSession() => Session.Initialize();
Common review questions
Before merging, ask:
- Can a new developer understand each name in 5 seconds?
- Does each method do one thing at one abstraction level?
- Are there flag arguments or too many parameters?
- Are there side effects not reflected by method names?
Summary
Clear naming and focused methods are the highest-ROI clean-code improvements in C#. Start there, then move to class design and architecture.