codewithmukesh/dotnet-claude-kit

modern-csharp

Modern C language features for .NET 10 and C 14.

View source
Original skill document

Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.

Modern C# (C# 14 / .NET 10)

Core Principles

  1. Use the newest stable features — C# 14 is the target. Prefer language-level constructs over library workarounds.
  2. Readability over cleverness — Pattern matching and expression-bodied members improve readability when used appropriately; deeply nested patterns do not.
  3. Value types where possible — Prefer record struct, Span<T>, and stack allocation to reduce GC pressure.
  4. Immutability by default — Use record, readonly, init, and required to make illegal states unrepresentable.

Patterns

Well-Known Features Quick Reference

FeatureUsageExample
Primary constructorsDI injection, eliminate field assignmentspublic class OrderService(IOrderRepo repo, TimeProvider clock) { }
Collection expressions[] for all collection types + spreadList<string> names = ["Alice", "Bob"]; / int[] all = [..a, ..b, 99];
RecordsDTOs, value objects, immutable datapublic record CreateOrderRequest(string CustomerId, List<OrderItem> Items);
readonly record structSmall stack-allocated value typespublic readonly record struct Money(decimal Amount, string Currency);
Pattern matchingSwitch expressions, list/property patternsorder switch { { Total: > 1000 } => "Premium", _ => "Standard" };
List patternsDeconstruct arrays/listsitems switch { [] => "Empty", [var x] => $"One: {x}", [var f, .., var l] => $"{f}..{l}" };
Span<T>Zero-allocation slicingReadOnlySpan<char> trimmed = input.Trim(); int.TryParse(trimmed[4..], out id);
Raw string literalsMulti-line SQL, JSON, XMLvar sql = """ SELECT ... """; / interpolated: $$""" {"id": "{{id}}"} """;
required membersEnforce initializationpublic required string ConnectionString { get; init; }
is pattern + extractionNull/type/property checkif (result is { IsSuccess: true, Value: var order }) { ... }

The field Keyword (C# 14)

Access the auto-generated backing field in property accessors without declaring it manually.

csharp
// GOOD — field keyword for validation in auto-property
public class Product
{
    public string Name
    {
        get => field;
        set => field = value?.Trim() ?? throw new ArgumentNullException(nameof(value));
    }

    public decimal Price
    {
        get => field;
        set => field = value >= 0 ? value : throw new ArgumentOutOfRangeException(nameof(value));
    }
}

Lazy Initialization with field

csharp
public class ProductCatalog
{
    // Lazy-load on first access — no manual Lazy<T> or backing field
    public IReadOnlyList<Product> Products
    {
        get => field ??= LoadProducts();
    }

    private static List<Product> LoadProducts() => /* expensive load */;
}

Change Notification with field

csharp
// INotifyPropertyChanged without manual backing fields
public class OrderViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    public string CustomerName
    {
        get => field;
        set
        {
            if (field == value) return;
            field = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CustomerName)));
        }
    } = "";

    public decimal Total
    {
        get => field;
        set
        {
            if (field == value) return;
            field = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Total)));
        }
    }
}

Extension Members (C# 14)

C# 14 adds extension blocks inside static classes. Unlike classic extension methods, they support extension properties and static extension members — the receiver is declared once for the whole block.

csharp
// GOOD — extension block (shipped C# 14 syntax)
public static class OrderExtensions
{
    extension(Order order)
    {
        public decimal TotalWithTax => order.Total * 1.2m;

        public bool IsHighValue => order.Total > 1000m;

        public string ToSummary() =>
            $"Order #{order.Id}: {order.Total:C} ({order.Items.Count} items)";
    }

    // Static extension members use the type (no receiver instance)
    extension(Order)
    {
        public static Order Empty => Order.Create("none", [], DateTimeOffset.MinValue);
    }
}

// Callers see them as if declared on Order
if (order.IsHighValue) { /* ... */ }

Classic this-parameter extension methods still work and coexist — use extension blocks when you need properties or several members on the same receiver.

Anti-patterns

Don't Use Obsolete Patterns When Modern Alternatives Exist

csharp
// BAD — manual backing field when field keyword works
private string _name;
public string Name
{
    get => _name;
    set => _name = value ?? throw new ArgumentNullException();
}

// BAD — old-style collection initialization
var list = new List<int>() { 1, 2, 3 };

// BAD — Tuple instead of record for domain types
(string Name, decimal Price) product = ("Widget", 9.99m);
// GOOD — record
public record Product(string Name, decimal Price);

Don't Over-pattern-match

csharp
// BAD — deeply nested pattern that's hard to read
if (order is { Customer: { Address: { Country: { Code: "US" } } } })

// GOOD — extract to a clear method or use sequential checks
if (order.Customer.Address.Country.Code == "US")

Don't Use var When the Type Is Not Obvious

csharp
// BAD — what type is this?
var result = Process(order);

// GOOD — explicit type when not obvious
Result<Order> result = Process(order);
// Also GOOD — var is fine when type is apparent
var orders = new List<Order>();

Decision Guide

ScenarioRecommendation
DTO / API contractrecord (reference type)
Small value object (2-3 fields)readonly record struct
Service with DIPrimary constructor
Collection creationCollection expression []
Property with validationfield keyword
Multi-line string (SQL, JSON)Raw string literal """
Slicing strings/arraysSpan<T>
Type checking + extractionPattern matching with is / switch
Enforced initializationrequired modifier
Adding methods to external typesExtension members
from this repository

More skills

All skills
codewithmukesh
Community

api-versioning

API versioning strategies for ASP.NET Core. Covers Asp.Versioning library, URL segment, header, and query string strategies, version deprecation, and OpenAPI integration. Load this skill when adding versioning to an API, evolving an API with breaking changes, or when the user mentions "API version", "versioning", "v1/v2", "Asp.Versioning", "deprecation", "breaking change", or "backward compatibility".

installs
2
GitHub stars
692
Updated
Aug 7
codewithmukesh
Community

arch-check

Architecture conformance check: verifies an existing codebase against its declared architecture (VSA, Clean Architecture, DDD, Modular Monolith) — dependency direction, layer violations, module boundary leaks, and cycles — using token-cheap Roslyn MCP analysis. Invoke when: "check architecture", "architecture violations", "layer violations", "dependency direction", "module boundaries", "arch check", "is my architecture clean", "enforce architecture", "conformance check". For CHOOSING an architecture, use architecture-advisor instead.

installs
2
GitHub stars
692
Updated
Aug 7
codewithmukesh
Community

architecture-advisor

Architecture selection advisor for .NET applications. Asks structured questions about domain complexity, team size, system lifetime, compliance, and integration needs, then recommends the best-fit architecture: Vertical Slice, Clean Architecture, DDD + Clean Architecture, or Modular Monolith. Load this skill when the user asks "which architecture", "choose architecture", "set up project", "new project", "architecture decision", "restructure", or "how should I organize". Always load BEFORE any architecture-specific skill.

installs
2
GitHub stars
692
Updated
Aug 7
codewithmukesh
Community

aspire

.NET Aspire for cloud-native orchestration. Covers AppHost configuration, service defaults, resource configuration, service discovery, and the Aspire dashboard. Load this skill when setting up local development orchestration, service discovery, or Aspire-managed infrastructure, or when the user mentions "Aspire", "AppHost", "service defaults", "service discovery", "orchestration", "Aspire dashboard", "AddProject", "WithReference", or "cloud-native .NET".

installs
2
GitHub stars
692
Updated
Aug 7