一键导入
coding-conventions
Use when applying or enforcing C# coding style — namespaces, sealed classes, var usage, XML docs.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when applying or enforcing C# coding style — namespaces, sealed classes, var usage, XML docs.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when designing gRPC services, proto files, or adding gRPC-Web or JSON transcoding.
Use when writing async code, propagating CancellationTokens, or fixing async/await pitfalls.
Use when applying modern C# idioms — records, pattern matching, primary constructors, collection expressions.
Use when registering services, choosing lifetimes, or implementing DI patterns like decorator or keyed services.
Use when selecting or implementing design patterns in C# — factory, builder, strategy, decorator, or mediator.
Use when implementing error handling with domain exceptions, ProblemDetails, or RpcException mapping.
| name | coding-conventions |
| description | Use when applying or enforcing C# coding style — namespaces, sealed classes, var usage, XML docs. |
| when_to_use | Use when applying or enforcing C# coding style — namespaces, sealed classes, var usage, XML docs. |
| metadata | {"category":"core","agent":"dotnet-architect"} |
// 1. File-scoped namespace (always)
namespace {Company}.{Domain}.Application.Features;
// 2. One primary type per file, named to match filename
// 3. Ordering: constants → fields → constructors → properties → methods
// Seal classes that are not designed for inheritance
public sealed class OrderService(IUnitOfWork unitOfWork) : IOrderService
{
// Primary constructor for DI (.NET 8+)
private readonly IUnitOfWork _unitOfWork = unitOfWork;
// Expression-bodied members for single-line methods
public Task<Order?> GetByIdAsync(Guid id, CancellationToken ct) =>
_unitOfWork.Orders.FindAsync(id, ct);
}
| Element | Convention | Example |
|---|---|---|
| Classes | PascalCase | OrderService |
| Interfaces | I + PascalCase | IOrderService |
| Methods | PascalCase | GetOrdersAsync |
| Async methods | Suffix Async | SaveChangesAsync |
| Properties | PascalCase | TotalAmount |
| Private fields | _camelCase | _unitOfWork |
| Parameters | camelCase | orderId |
| Constants | PascalCase | MaxRetryCount |
| Enums | PascalCase (singular) | OrderStatus |
// ✅ Use var when type is obvious from right side
var order = new Order();
var orders = await _repository.GetAllAsync(ct);
var count = orders.Count;
// ❌ Don't use var when type is not obvious
decimal total = CalculateTotal(items); // Not: var total = ...
IOrderService service = GetService(); // Not: var service = ...
// Use records for immutable data (commands, events, DTOs)
public sealed record CreateOrderCommand(
string CustomerName,
decimal Total,
List<OrderItemDto> Items) : IRequest<Result<Guid>>;
// Use record for output DTOs
public sealed record OrderOutput(
Guid Id,
string CustomerName,
decimal Total,
string Status);
// Always accept CancellationToken
public async Task<Result<Order>> Handle(
CreateOrderCommand request,
CancellationToken cancellationToken)
{
// Always pass CancellationToken to async calls
var order = await _repository.FindAsync(request.Id, cancellationToken);
// Never use async void — always return Task
// Never use .Result or .Wait() — always await
}
// Use nullable reference types
public Order? FindById(Guid id) => ...
// Use pattern matching for null checks
if (order is null)
throw new NotFoundException(nameof(Order), id);
// Use null-conditional and null-coalescing
var name = order?.CustomerName ?? "Unknown";
/// <summary>
/// Creates a new order with the specified items.
/// </summary>
/// <param name="command">The create order command.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>The created order ID wrapped in a Result.</returns>
/// <exception cref="ValidationException">When command validation fails.</exception>
public Task<Result<Guid>> Handle(CreateOrderCommand command, CancellationToken cancellationToken);
| Anti-Pattern | Correct Approach |
|---|---|
public string Name { get; set; } on domain entities | public string Name { get; private set; } |
async void methods | Always return Task or Task<T> |
.Result or .Wait() on tasks | Always await |
Catching generic Exception | Catch specific exceptions |
| String concatenation for SQL | Parameterized queries |
DateTime.Now | Injected TimeProvider or ISystemClock |
grep -r "namespace " --include="*.cs" | head -5 # Namespace style
grep -r "sealed class" --include="*.cs" | wc -l # Sealed usage
grep -r "var " --include="*.cs" | head -10 # Var usage
This skill depends on the always-on coding-style convention rule:
The rule is loaded into context whenever this skill is active (FR-011 universal whitelist).
3. Check .editorconfig for project-specific overrides