Skip to content
Development
Skill

/dotnet-techne-csharp-coding-standards

Use when writing or refactoring modern C# with maintainability and performance standards. Keywords: coding standards, C# best practices, refactor C#, records, pattern matching, async best practices.

From plugin
dotnet-episteme-skills
1314 skills13 agents3 commands3 hooks
+1

Claude Code

$ npx -y skills add Metalnib/dotnet-episteme-skills --skill dotnet-techne-csharp-coding-standards --agent claude-code

SKILL.md

dotnet-techne-csharp-coding-standards.SKILL.md
name: dotnet-techne-csharp-coding-standards
description: "Use when writing or refactoring modern C# with maintainability and performance standards. Keywords: coding standards, C# best practices, refactor C#, records, pattern matching, async best practices."
disable-model-invocation: false
user-invocable: true
metadata:
  author: Metalnib
  version: "1.0.0"
  trigger_keywords:
    - coding standards
    - c# best practices
    - refactor c#
    - records
    - pattern matching
    - async best practices

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.

// 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.

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.

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.

// 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

// 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 cancellati
Read more
@metalnib
Ships withdotnet-episteme-skills

DotNet Episteme Skills - a curated, manual-first .NET AI skills library rooted in systematic knowledge (episteme) and shaped by disciplined craft (techne), designed for engineers who prioritise precision over hype.

1314 skills13 agents1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
13
Star history of Metalnib/dotnet-episteme-skills on GitHub, a chart by star-history.com

Other skills on dotnet-episteme-skills.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills13d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react4d252k
@facebook@facebookInstall Skill

Questions about dotnet-techne-csharp-coding-standards.

Which coding agents can use dotnet-techne-csharp-coding-standards?
dotnet-techne-csharp-coding-standards installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.