Modern Csharp

codewithmukesh/dotnet-claude-kit/skills/modern-csharp

by codewithmukesh23300897f4d1No license754 starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 2 months ago

Modern C# language features for .NET 10 and C# 14. Covers primary constructors, collection expressions, the field keyword, extension members, records, pattern matching, spans, and raw string literals. Load this skill when writing any new C# code, reviewing existing code for modernization, using "modern C#", "C# 14", "primary constructor", "collection expression", "records", "pattern matching", "span", "field keyword", or "extension members". Always loaded as the baseline for all agents.

Instructions only

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-propertypublic 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 fieldspublic 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 Orderif (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 worksprivate string _name;public string Name{    get => _name;    set => _name = value ?? throw new ArgumentNullException();}
// BAD — old-style collection initializationvar list = new List<int>() { 1, 2, 3 };
// BAD — Tuple instead of record for domain types(string Name, decimal Price) product = ("Widget", 9.99m);// GOOD — recordpublic record Product(string Name, decimal Price);

Don't Over-pattern-match

csharp
// BAD — deeply nested pattern that's hard to readif (order is { Customer: { Address: { Country: { Code: "US" } } } })
// GOOD — extract to a clear method or use sequential checksif (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 obviousResult<Order> result = Process(order);// Also GOOD — var is fine when type is apparentvar 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

Source and attribution

Source:codewithmukesh/dotnet-claude-kitinskills/modern-csharpat commit2330089

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal

More from codewithmukesh/dotnet-claude-kit

Wrap Up

codewithmukesh

Captures end-of-session work, pending tasks and learnings into a handoff file, and reloads it at session start.

Productivity & Workflow754updated 2 months ago

Workflow Mastery

codewithmukesh

Claude Code workflow mastery for .NET developers. Covers parallel execution with git worktrees, plan mode strategy, verification loops, auto-formatting hooks, permission setup for dotnet CLI, prompting techniques, subagent patterns, and context discipline — token budget management, MCP-first navigation, lazy loading, and subagent isolation — all adapted for the .NET ecosystem. Load this skill when setting up Claude Code for a .NET project, optimizing workflows, running parallel sessions, when context is running low or sessions feel sluggish, when exploring a large codebase efficiently, or when the user mentions "productivity", "workflow", "parallel", "worktree", "plan mode", "permissions", "hooks", "10x", "setup Claude Code", "speed up development", "context", "tokens", "budget", "running out of context", "too many files", or "large codebase". Inspired by tips from Boris Cherny (creator of Claude Code) and the Anthropic team.

Awaiting classification754updated 2 months ago

Vertical Slice

codewithmukesh

Guides .NET developers in structuring applications with Vertical Slice Architecture, covering feature folders, endpoint grouping and handler patterns.

Software Development754updated 2 months ago

Testing

codewithmukesh

Testing strategy for .NET 10 applications. Covers xUnit v3, WebApplicationFactory for integration tests, Testcontainers for real database testing, Verify for snapshot testing, and the AAA pattern. Load this skill when writing tests, setting up test infrastructure, reviewing test coverage, or when the user mentions "test", "xUnit", "WebApplicationFactory", "Testcontainers", "integration test", "unit test", "bUnit", "snapshot test", "Verify", "test coverage", "AAA pattern", "WireMock", or "FakeTimeProvider".

Awaiting classification754updated 2 months ago

Tdd

codewithmukesh

Guided test-driven development workflow for .NET 10 using xUnit v3, WebApplicationFactory, Testcontainers, and Verify snapshots. Follows the strict red-green-refactor cycle. Use when: "TDD", "test-driven", "let's TDD this", "red green refactor", "write the test first", or when building a feature with clear acceptance criteria.

Awaiting classification754updated 2 months ago

Spec

codewithmukesh

Turns a vague feature idea into an agreed, persisted specification file through structured questioning rounds.

Productivity & Workflow754updated 2 months ago