К основному содержанию
скилл CX Codex

modern-csharp-coding-standards — скилл для Claude Code

Задаёт правила современного C# 12+: неизменяемые рекорды, pattern matching, структуры Span<T> и асинхронный код без лишних аллокаций памяти.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add Aaronontheweb/dotnet-skills --skill modern-csharp-coding-standards -a claude-code
npx skills add Aaronontheweb/dotnet-skills --skill csharp-coding-standards -a claude-code
Открыть на GitHub

Что делает modern-csharp-coding-standards

Скилл инструктирует ассистента при создании новых классов, проектировании публичных API и рефакторинге на C# 12+. Основной упор сделан на неизменяемость по умолчанию и отказ от абстрактных базовых классов в пользу композиции. Для сущностей и DTO предлагается объявлять record class, а для объектов-значений — строго readonly record struct с явным приведением типов без неявных операторов.

В производительных сценариях скилл требует применять Span<T> для синхронных участков без аллокаций, Memory<T> для асинхронного кода и ArrayPool<T> под временные буферы. Асинхронные методы обязаны принимать CancellationToken со значением по умолчанию, использовать ConfigureAwait(false) в библиотеках и возвращать ValueTask, если результат часто доступен синхронно. Для ожидаемых ошибок скилл предписывает предметные Result-типы вместо выброса исключений.

В проекте придётся включить <Nullable>enable</Nullable>, иначе правила безопасной работы с null потеряют смысл.

Какие задачи решает

  • переписать классы предметной области на record и readonly record struct
  • убрать лишние аллокации памяти с помощью Span<T> и Memory<T>
  • настроить обработку отмены в асинхронных методах через CancellationToken
  • заменить наследование и абстрактные классы интерфейсной композицией

Примеры запросов агенту

  • Спроектируй модель заказа с использованием readonly record struct для идентификаторов и Result-типа для ошибок
  • Оптимизируй этот парсер бинарных данных через Span<T> без лишних аллокаций
  • Проведи рефакторинг сервиса: добавь CancellationToken во все асинхронные методы и включи nullable-проверки

Как установить modern-csharp-coding-standards

1Через Skills CLI (Vercel)

npx skills add Aaronontheweb/dotnet-skills --skill modern-csharp-coding-standards -a claude-code
npx skills add Aaronontheweb/dotnet-skills --skill csharp-coding-standards -a claude-code

2Вручную: положить файлы

~/.claude/skills/csharp-coding-standards/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/csharp-coding-standards/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора32

efcore-patterns Скилл для работы с Entity Framework Core: настройка NoTracking, разбиение запросов, миграции и типичные ошибки. CX Codex +1 1 600установок csharp-concurrency-patterns Помогает агенту выбирать подходящие абстракции многопоточности в .NET: от async/await до Channels и Akka.NET. Пригодится при проектировании очередей и избавлении от блокировок. CX Codex +1 1 600установок dependency-injection-patterns Скилл учит раскладывать регистрации сервисов в ASP.NET Core по расширениям IServiceCollection, чтобы Program.cs не распухал. CX Codex +1 668установок database-performance Скилл задаёт правила производительности баз данных для .NET: разделяет чтение и запись, устраняет N+1 запросы и требует лимиты на выборки. CX Codex +1 664установок api-design Скилл для проектирования публичных API по принципу «только расширять»: помогает не ломать совместимость при выпуске новых версий. CX Codex +1 660установок dotnet-project-structure Скилл подсказывает агенту, как разложить .NET-решение: .slnx, Directory.Build.props, центральные версии пакетов и SourceLink. CX Codex +1 658установок type-design-performance Скилл для проектирования типов .NET с оглядкой на производительность: запечатанные классы, readonly-структуры, отложенный перебор коллекций. CX Codex +1 655установок ilspy-decompile Декомпилирует сборки .NET через утилиту ilspycmd. Помогает изучать исходники пакетов NuGet и внутреннее устройство runtime-библиотек прямо в сессии агента. CX Codex +1 602установок

Похожие

csharp-async официальный github Скилл подсказывает правила асинхронного C# и помогает находить ошибки в коде. Пригодится для ревью методов, задач и API. 10 883установок csharp официальный github Правило задаёт Copilot стиль C#-кода: именование, nullable-типы, форматирование и работу с ASP.NET Core. Пригодится, если агент пишет по-разному в каждом файле. ★ 40 418звёзд репо csharp-pro Seth Hobson Субагент для Claude, Codex и Cursor, который пишет современный C# и разбирает сложные .NET-задачи: рефакторинг, async, тесты. CX Codex ★ 41 729звёзд репо java-coding-standards affaan-m Скилл применяет правила Java к коду для Spring Boot и Quarkus. Подключайте его при написании или ревью сервисов на этих фреймворках. CX Codex +1 5 100установок csharp-refactoring dotnet Скилл проводит рефакторинг C#/.NET так, чтобы поведение кода не менялось: сначала классифицирует запрос, потом правит по биндингам и проверяет сборкой с тестами. CX Codex +1 1 800установок

Рядом в теме «Языки программирования»

Все скиллы по теме «Языки программирования» →

Вопросы о modern-csharp-coding-standards

Как установить modern-csharp-coding-standards в Claude Code?

Выполните команду npx skills add Aaronontheweb/dotnet-skills --skill modern-csharp-coding-standards -a claude-code.

Что делает скилл modern-csharp-coding-standards?

Он направляет агента писать код по стандартам C# 12+: требует рекорды для неизменяемых данных, pattern matching, безопасную работу с null, zero-allocation типы вроде Span<T> и дисциплину async/await.

Как скилл рекомендует обрабатывать ожидаемые ошибки?

Для ожидаемых сбоев предписано использовать специализированные доменные Result-типы вместо общих классов или исключений, оставляя throw исключительно для непредвиденных критических ситуаций.

Исходный текст

SKILL.md · MIT
---
name: modern-csharp-coding-standards
description: Write modern, high-performance C# code using records, pattern matching, value objects, async/await, Span<T>/Memory<T>, and best-practice API design patterns. Emphasizes functional-style programming with C# 12+ features.
user-invocable: false
---

# Modern C# Coding Standards

## When to Use This Skill

Use this skill when:
- Writing new C# code or refactoring existing code
- Designing public APIs for libraries or services
- Optimizing performance-critical code paths
- Implementing domain models with strong typing
- Building async/await-heavy applications
- Working with binary data, buffers, or high-throughput scenarios

## Reference Files

- [value-objects-and-patterns.md](value-objects-and-patterns.md): Full value object examples and pattern matching code
- [performance-and-api-design.md](performance-and-api-design.md): Span<T>/Memory<T> examples and API design principles
- [composition-and-error-handling.md](composition-and-error-handling.md): Composition over inheritance, Result type, testing patterns
- [anti-patterns-and-reflection.md](anti-patterns-and-reflection.md): Reflection avoidance and common anti-patterns

## Core Principles

1. **Immutability by Default** - Use `record` types and `init`-only properties
2. **Type Safety** - Leverage nullable reference types and value objects
3. **Modern Pattern Matching** - Use `switch` expressions and patterns extensively
4. **Async Everywhere** - Prefer async APIs with proper cancellation support
5. **Zero-Allocation Patterns** - Use `Span<T>` and `Memory<T>` for performance-critical code
6. **API Design** - Accept abstractions, return appropriately specific types
7. **Composition Over Inheritance** - Avoid abstract base classes, prefer composition
8. **Value Objects as Structs** - Use `readonly record struct` for value objects

---

## Language Patterns

### Records for Immutable Data (C# 9+)

Use `record` types for DTOs, messages, events, and domain entities.

```csharp
// Simple immutable DTO
public record CustomerDto(string Id, string Name, string Email);

// Record with validation in constructor
public record EmailAddress
{
    public string Value { get; init; }

    public EmailAddress(string value)
    {
        if (string.IsNullOrWhiteSpace(value) || !value.Contains('@'))
            throw new ArgumentException("Invalid email address", nameof(value));

        Value = value;
    }
}

// Records with collections - use IReadOnlyList
public record ShoppingCart(
    string CartId,
    string CustomerId,
    IReadOnlyList<CartItem> Items
)
{
    public decimal Total => Items.Sum(item => item.Price * item.Quantity);
}
```

**When to use `record class` vs `record struct`:**
- `record class` (default): Reference types, use for entities, aggregates, DTOs with multiple properties
- `record struct`: Value types, use for value objects (see next section)

### Value Objects as readonly record struct

Value objects should **always be `readonly record struct`** for performance and value semantics. Use explicit conversions, never implicit operators.

```csharp
public readonly record struct OrderId(string Value)
{
    public OrderId(string value) : this(
        !string.IsNullOrWhiteSpace(value)
            ? value
            : throw new ArgumentException("OrderId cannot be empty", nameof(value)))
    { }
    public override string ToString() => Value;
}

public readonly record struct Money(decimal Amount, string Currency);
public readonly record struct CustomerId(Guid Value)
{
    public static CustomerId New() => new(Guid.NewGuid());
}
```

See [value-objects-and-patterns.md](value-objects-and-patterns.md) for complete examples including multi-value objects, factory patterns, and the no-implicit-conversion rule.

### Pattern Matching (C# 8-12)

Use switch expressions, property patterns, relational patterns, and list patterns for cleaner code.

```csharp
public decimal CalculateDiscount(Order order) => order switch
{
    { Total: > 1000m } => order.Total * 0.15m,
    { Total: > 500m } => order.Total * 0.10m,
    { Total: > 100m } => order.Total * 0.05m,
    _ => 0m
};
```

See [value-objects-and-patterns.md](value-objects-and-patterns.md) for full pattern matching examples.

---

### Nullable Reference Types (C# 8+)

Enable nullable reference types in your project and handle nulls explicitly.

```csharp
// In .csproj
<PropertyGroup>
    <Nullable>enable</Nullable>
</PropertyGroup>

// Explicit nullability
public string? FindUserName(string userId)
{
    var user = _repository.Find(userId);
    return user?.Name;
}

// Pattern matching with null checks
public decimal GetDiscount(Customer? customer) => customer switch
{
    null => 0m,
    { IsVip: true } => 0.20m,
    { OrderCount: > 10 } => 0.10m,
    _ => 0.05m
};

// Guard clauses with ArgumentNullException.ThrowIfNull (C# 11+)
public void ProcessOrder(Order? order)
{
    ArgumentNullException.ThrowIfNull(order);
    // order is now non-nullable in this scope
    Console.WriteLine(order.Id);
}
```

---

## Composition Over Inheritance

**Avoid abstract base classes.** Use interfaces + composition. Use static helpers for shared logic. Use records with factory methods for variants.

See [composition-and-error-handling.md](composition-and-error-handling.md) for full examples.

---

## Performance Patterns

### Async/Await Best Practices

```csharp
// Async all the way - always accept CancellationToken
public async Task<Order> GetOrderAsync(string orderId, CancellationToken cancellationToken)
{
    var order = await _repository.GetAsync(orderId, cancellationToken);
    return order;
}

// ValueTask for frequently-called, often-synchronous methods
public ValueTask<Order?> GetCachedOrderAsync(string orderId, CancellationToken cancellationToken)
{
    if (_cache.TryGetValue(orderId, out var order))
        return ValueTask.FromResult<Order?>(order);
    return GetFromDatabaseAsync(orderId, cancellationToken);
}

// IAsyncEnumerable for streaming
public async IAsyncEnumerable<Order> StreamOrdersAsync(
    string customerId,
    [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
    await foreach (var order in _repository.StreamAllAsync(cancellationToken))
    {
        if (order.CustomerId == customerId)
            yield return order;
    }
}
```

**Key rules:**
- Always accept `CancellationToken` with `= default`
- Use `ConfigureAwait(false)` in library code
- Never block on async code (no `.Result` or `.Wait()`)
- Use linked CancellationTokenSource for timeouts

### Span<T> and Memory<T>

Use `Span<T>` for synchronous zero-allocation operations, `Memory<T>` for async, and `ArrayPool<T>` for large temporary buffers.

See [performance-and-api-design.md](performance-and-api-design.md) for complete Span/Memory examples and the API design section.

---

## Error Handling: Result Type

For expected errors, use a domain-specific result type instead of exceptions, not a generic `Result<T>`. Use exceptions only for unexpected/system errors.

See [composition-and-error-handling.md](composition-and-error-handling.md) for the full Result type implementation and usage examples.

---

## Avoid Reflection-Based Metaprogramming

**Banned:** AutoMapper, Mapster, ExpressMapper. Use explicit mapping extension methods instead. Use `UnsafeAccessorAttribute` (.NET 8+) when you genuinely need private member access.

See [anti-patterns-and-reflection.md](anti-patterns-and-reflection.md) for full guidance.

---

## Code Organization

```csharp
// File: Domain/Orders/Order.cs

namespace MyApp.Domain.Orders;

// 1. Primary domain type
public record Order(
    OrderId Id,
    CustomerId CustomerId,
    Money Total,
    OrderStatus Status,
    IReadOnlyList<OrderItem> Items
)
{
    public bool IsCompleted => Status is OrderStatus.Completed;

    public Result<Order, OrderError> AddItem(OrderItem item)
    {
        if (Status is not OrderStatus.Draft)
            return Result<Order, OrderError>.Failure(
                new OrderError("ORDER_NOT_DRAFT", "Can only add items to draft orders"));

        var newItems = Items.Append(item).ToList();
        var newTotal = new Money(
            Items.Sum(i => i.Total.Amount) + item.Total.Amount,
            Total.Currency);

        return Result<Order, OrderError>.Success(
            this with { Items = newItems, Total = newTotal });
    }
}

// 2. Enums for state
public enum OrderStatus { Draft, Submitted, Processing, Completed, Cancelled }

// 3. Related types
public record OrderItem(ProductId ProductId, Quantity Quantity, Money UnitPrice)
{
    public Money Total => new(UnitPrice.Amount * Quantity.Value, UnitPrice.Currency);
}

// 4. Value objects
public readonly record struct OrderId(Guid Value)
{
    public static OrderId New() => new(Guid.NewGuid());
}

// 5. Errors
public readonly record struct OrderError(string Code, string Message);
```

---

## Best Practices Summary

### DO's
- Use `record` for DTOs, messages, and domain entities
- Use `readonly record struct` for value objects
- Leverage pattern matching with `switch` expressions
- Enable and respect nullable reference types
- Use async/await for all I/O operations
- Accept `CancellationToken` in all async methods
- Use `Span<T>` and `Memory<T>` for high-performance scenarios
- Accept abstractions (`IEnumerable<T>`, `IReadOnlyList<T>`)
- Use `Result<T, TError>` for expected errors
- Pool buffers with `ArrayPool<T>` for large allocations
- Prefer composition over inheritance

### DON'Ts
- Don't use mutable classes when records work
- Don't use classes for value objects (use `readonly record struct`)
- Don't create deep inheritance hierarchies
- Don't ignore nullable reference type warnings
- Don't block on async code (`.Result`, `.Wait()`)
- Don't use `byte[]` when `Span<byte>` suffices
- Don't forget `CancellationToken` parameters
- Don't return mutable collections from APIs
- Don't throw exceptions for expected business errors
- Don't allocate large arrays repeatedly (use `ArrayPool`)

See [anti-patterns-and-reflection.md](anti-patterns-and-reflection.md) for detailed anti-pattern examples.

---

## Additional Resources

- **C# Language Specification**: https://learn.microsoft.com/en-us/dotnet/csharp/
- **Pattern Matching**: https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/pattern-matching
- **Span<T> and Memory<T>**: https://learn.microsoft.com/en-us/dotnet/standard/memory-and-spans/
- **Async Best Practices**: https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming
- **.NET Performance Tips**: https://learn.microsoft.com/en-us/dotnet/framework/performance/

© Aaronontheweb · MIT · Aaronontheweb/dotnet-skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой