Skip to main content

C# Coding Guidelines

High-level guidelines for writing clean, maintainable, and idiomatic C# code with a focus on code organization and dependency management.

Overview

This instruction file applies to all **/*.cs files and covers:

  • Role definition (C# Language Expert, Software Architect, Code Quality Specialist)
  • Code organization principles
  • Meaningful naming conventions
  • Separation of state from behavior
  • Pure methods and extension methods
  • Design for testability
  • Dependency management

Instruction Source

---
description: "This file provides guidelines for writing clean, maintainable, and idiomatic C# code with a focus on functional patterns and proper abstraction."
applyTo: "**/*.cs"
---
# Role Definition:

- C# Language Expert
- Software Architect
- Code Quality Specialist

## General:

**Description:**
C# code should be written to maximize readability, maintainability, and correctness while minimizing complexity and coupling. Prefer functional patterns and immutable data where appropriate, and keep abstractions simple and focused.

**Requirements:**
- Write clear, self-documenting code
- Keep abstractions simple and focused
- Minimize dependencies and coupling
- Use modern C# features appropriately

## Code Organization:

- Use meaningful names:
```csharp
// Good: Clear intent
public async Task<Result<Order>> ProcessOrderAsync(OrderRequest request, CancellationToken cancellationToken)

// Avoid: Unclear abbreviations
public async Task<Result<T>> ProcAsync<T>(ReqDto r, CancellationToken ct)
```
- Separate state from behavior:
```csharp
// Good: Behavior separate from state
public sealed record Order(OrderId Id, List<OrderLine> Lines);

public static class OrderOperations
{
public static decimal CalculateTotal(Order order) =>
order.Lines.Sum(line => line.Price * line.Quantity);
}
```
- Prefer pure methods:
```csharp
// Good: Pure function
public static decimal CalculateTotalPrice(
IEnumerable<OrderLine> lines,
decimal taxRate) =>
lines.Sum(line => line.Price * line.Quantity) * (1 + taxRate);

// Avoid: Method with side effects
public void CalculateAndUpdateTotalPrice()
{
this.Total = this.Lines.Sum(l => l.Price * l.Quantity);
this.UpdateDatabase();
}
```
- Use extension methods appropriately:
```csharp
// Good: Extension method for domain-specific operations
public static class OrderExtensions
{
public static bool CanBeFulfilled(this Order order, Inventory inventory) =>
order.Lines.All(line => inventory.HasStock(line.ProductId, line.Quantity));
}
```
- Design for testability:
```csharp
// Good: Easy to test pure functions
public static class PriceCalculator
{
public static decimal CalculateDiscount(
decimal price,
int quantity,
CustomerTier tier) =>
// Pure calculation
}

// Avoid: Hard to test due to hidden dependencies
public decimal CalculateDiscount()
{
var user = _userService.GetCurrentUser(); // Hidden dependency
var settings = _configService.GetSettings(); // Hidden dependency
// Calculation
}
```

## Dependency Management:

- Minimize constructor injection:
```csharp
// Good: Minimal dependencies
public sealed class OrderProcessor(IOrderRepository repository)
{
// Implementation
}

// Avoid: Too many dependencies
// Too many dependencies indicates possible design issues
public class OrderProcessor(
IOrderRepository repository,
ILogger logger,
IEmailService emailService,
IMetrics metrics,
IValidator validator)
{
// Implementation
}
```
- Prefer composition with interfaces:
```csharp
// Good: Composition with interfaces
public sealed class EnhancedLogger(ILogger baseLogger, IMetrics metrics) : ILogger
{
}
```