csharp-modern

.NET 8+, nullable enabled, async-first, records for data.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "csharp-modern" with this command: npx skills add phrazzld/claude-config/phrazzld-claude-config-csharp-modern

Modern C#

.NET 8+, nullable enabled, async-first, records for data.

Async Patterns

Always use async/await for I/O. Always pass CancellationToken :

public async Task<User?> GetUserAsync( int id, CancellationToken cancellationToken = default) { using var connection = await _factory .CreateConnectionAsync(cancellationToken) .ConfigureAwait(false);

return await connection
    .QuerySingleOrDefaultAsync&#x3C;User>(sql, cancellationToken: cancellationToken)
    .ConfigureAwait(false);

}

ConfigureAwait(false) in library code. Never block on async (.Result , .Wait() ).

Nullable Reference Types

Enable project-wide. Treat warnings as errors:

<Nullable>enable</Nullable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>

Explicit nullability:

// Nullable when user might not exist Task<User?> GetByIdAsync(int id);

// Non-nullable with exception on not found Task<User> GetRequiredByIdAsync(int id);

// Handle nulls explicitly if (user is not null) { ProcessUser(user); } var name = user?.Name ?? "Anonymous";

Records & Immutability

Records for DTOs and value types:

// DTO public record CreateOrderRequest( string CustomerId, IReadOnlyList<OrderItemDto> Items);

// Domain entity public record class Order { public string Id { get; init; } public OrderStatus Status { get; init; }

public Order Ship() => this with { Status = OrderStatus.Shipped };

}

// Value type (<16 bytes) public readonly record struct Money(decimal Amount, string Currency);

Never expose mutable collections. Use IReadOnlyList<T> .

Pattern Matching

Switch expressions over if-else chains:

public decimal CalculateDiscount(object discount) => discount switch { decimal amount => amount, int percentage => percentage / 100m, string code => GetDiscountForCode(code), _ => throw new ArgumentException("Unsupported type") };

public string GetShipping(Order order) => order switch { { TotalAmount: > 100, Customer.IsPremium: true } => "Free Express", { TotalAmount: > 100 } => "Free Standard", _ => "Standard" };

Project Setup

<!-- Directory.Build.props --> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <LangVersion>12.0</LangVersion> <Nullable>enable</Nullable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisLevel>latest-recommended</AnalysisLevel> </PropertyGroup>

Anti-Patterns

  • Blocking on async (.Result , .Wait() )

  • async void outside event handlers

  • Missing ConfigureAwait(false) in libraries

  • null! without documented justification

  • Mutable DTOs with public setters

  • Switch statements over switch expressions

  • Legacy .csproj or packages.config

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

pencil-renderer

No summary provided by upstream source.

Repository SourceNeeds Review
General

ui-skills

No summary provided by upstream source.

Repository SourceNeeds Review
General

llm-gateway-routing

No summary provided by upstream source.

Repository SourceNeeds Review