csharp-api-controller-…
Defines the coding standards, patterns, and conventions for ASP.NET Core REST API controllers. Rules cover routing, HTTP verbs, response types, XML…
Defines the C# coding standards, patterns, and conventions to be applied consistently across all C# projects. Rules cover naming, structure, async patterns, null handling, dependency injection, logging, result patterns, and formatting. Apply these rules uniformly in all
$ npx -y skills add linuxchata/ai-playbook --skill csharp-coding-standards --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/csharp-coding-standardsContext preview
The summary Claude sees to decide when to auto-load this skill.
Defines the C# coding standards, patterns, and conventions to be applied consistently across all C# projects. Rules cover naming, structure, async patterns, null handling, dependency injection, logging, result patterns, and formatting. Apply these rules uniformly in all
name: csharp-coding-standards description: Defines the C# coding standards, patterns, and conventions to be applied consistently across all C# projects. Rules cover naming, structure, async patterns, null handling, dependency injection, logging, result patterns, and formatting. Apply these rules uniformly in all production code. metadata: version: 1.1.0
Defines the C# coding standards, patterns, and conventions to be applied consistently across all C# projects. Rules cover naming, structure, async patterns, null handling, dependency injection, logging, result patterns, and formatting. Apply these rules uniformly in all production code.
---
Always use **file-scoped namespaces**:
// ✅ Correct
namespace MyApp.Core.Validators;
internal class OrderValidator { }
// ❌ Wrong
namespace MyApp.Core.Validators
{
internal class OrderValidator { }
}using System.Text; using System.Text.Json; using Microsoft.Extensions.Logging; using MyApp.Core.Abstractions; using MyApp.Domain;
Each file contains exactly one top-level type. The file name must match the type name exactly.
---
| Kind | Convention | Example | |---|---|---| | Classes | PascalCase | `OrderValidator`, `UserService` | | Interfaces | `I` prefix + PascalCase | `IOrderRepository`, `IUserService` | | Enums | PascalCase | `OrderStatus`, `PaymentMethod` | | Structs | PascalCase | `Money`, `DateRange` | | Records | PascalCase | `AppConfiguration`, `UserSettings` |
| Kind | Convention | Example | |---|---|---| | Public properties | PascalCase | `CreatedAt`, `TotalAmount` | | Public methods | PascalCase | `CreateOrder`, `ValidatePayment` | | Private fields | `_camelCase` (underscore prefix) | `_repository`, `_logger` | | Constants | PascalCase | `DefaultTimeout`, `MaxRetryCount` | | Local variables | camelCase | `orderId`, `serializedData` | | Method parameters | camelCase | `cancellationToken`, `userId` | | Lambda parameters | Short camelCase | `x =>`, `e =>`, `o =>` |
> **All async methods MUST end with the `Async` suffix without exception.**
// ✅ Correct public async Task<Order?> GetByIdAsync(Guid id, CancellationToken cancellationToken); // ❌ Wrong – missing Async suffix public async Task<Order?> GetById(Guid id, CancellationToken cancellationToken);
This applies to:
---
// ✅ Correct: public sealed for types exposed via public interface
public sealed class OrderService : IOrderService { }
// ✅ Correct: internal sealed for infrastructure implementations
internal sealed class SqlOrderRepository : IOrderRepository { }Mark classes `sealed` by default unless inheritance is explicitly required. This prevents unintended derivation and enables JIT optimizations.
---
// ✅ Early return guard
if (id is null || id.Length == 0)
{
return null;
}Use modern `ArgumentNullException` helpers for public/internal method boundaries:
// ✅ Correct ArgumentNullException.ThrowIfNull(order); ArgumentNullException.ThrowIfNullOrEmpty(order.UserName);
Prefer `?.` and `??` / `??=` over verbose null checks in expressions:
// ✅ Correct return items?.Select(x => x.ToDto()).ToArray(); var name = input?.Trim() ?? string.Empty;
---
Always inject dependencies via the constructor. Store them as `private readonly` fields prefixed with `_`.
private readonly IOrderRepository _orderRepository;
private readonly ILogger<OrderService> _logger;
public OrderService(IOrderRepository orderRepository, ILogger<OrderService> logger)
{
_orderRepository = orderRepository;
_logger = logger;
}Access configuration via `IOptions<T>`. Extract `.Value` in the constructor and store as a field – do not access `.Value` repeatedly at call sites.
private readonly AppConfiguration _configuration;
public OrderService(IOptions<AppConfiguration> options)
{
_configuration = options.Value;
}Centralize all service registrations in a dedicated `DependencyInjection.cs` static class with `IServiceCollection` extension methods.
public static class DependencyInjection
{
public static void AddMyFeature(this IServiceCollection services, IConfiguration configuration)
{
services.AddTransient<IOrderService, OrderService>();
services.AddKeyedTransient<IPaymentStrategy, CreditCardStrategy>("creditcard");
}
}Lifetime guidance:
Rules, skills, and guidelines for AI coding assistants – Claude, Cursor, and beyond.
Repo: linuxchata/ai-playbook
Defines the coding standards, patterns, and conventions for ASP.NET Core REST API controllers. Rules cover routing, HTTP verbs, response types, XML…
Defines the testing standards, patterns, and conventions for all C# unit and integration test projects. Rules cover test framework usage, naming, structure,…