
Dotnet 10 Csharp 14
Keep new .NET 10 and C# 14 code aligned with modern DI, HTTP, resilience, and language features while avoiding common anti-patterns.
Overview
dotnet-10-csharp-14 is an agent skill for the Build phase that lists .NET 10 and C# 14 anti-patterns with corrected HttpClient, DI, API, and language patterns.
Install
npx skills add https://github.com/mhagrelius/dotfiles --skill dotnet-10-csharp-14What is this skill?
- Quick-reference table maps 12 common anti-patterns to .NET 10 / C# 14 replacements
- HttpClient: inject IHttpClientFactory or typed clients—never per-request new HttpClient()
- APIs: prefer TypedResults.Ok() over Results.Ok(); use AddStandardResilienceHandler() over manual Polly
- C# 14: field keyword, extension blocks, null-conditional assignment (x?.Prop = y)
- DI safety: ValidateOnStart(), avoid singleton→scoped captive deps, Interlocked for singleton counters
- 12-row quick reference: anti-pattern versus recommended .NET 10 / C# 14 pattern
Adoption & trust: 1.6k installs on skills.sh; 2 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are generating C# quickly and keep slipping into HttpClient leaks, Results.Ok(), blocking async, and pre-C# 14 style.
Who is it for?
Indie backend devs on .NET 10 who want an agent-readable cheat sheet during feature work and small refactors.
Skip if: Greenfield learners needing a tutorial series, or teams on older .NET versions where C# 14 features are unavailable.
When should I use this skill?
User is writing or refactoring .NET 10 / C# 14 backend code and needs anti-pattern guardrails (implicit via dotfiles skill bundle).
What do I get? / Deliverables
New and edited code follows injectable HTTP, typed minimal API results, resilience defaults, and current C# idioms from the reference table.
- Code snippets aligned to documented correct patterns
- Fewer DI lifetime and HttpClient misuse issues in generated edits
Recommended Skills
Journey fit
Build is where API and service code is written; this skill is a shelf reference during implementation and refactors. backend matches HttpClient factory, TypedResults, ErrorOr, and ASP.NET-style service patterns in the anti-pattern guide.
How it compares
Reference checker skill—not a project template, test runner, or Azure deploy workflow.
Common Questions / FAQ
Who is dotnet-10-csharp-14 for?
Solo and small-team C# builders using Claude or similar agents to write APIs and services on .NET 10 with C# 14.
When should I use dotnet-10-csharp-14?
During Build backend work whenever you add endpoints, HTTP clients, DI registrations, or refactor legacy patterns in the same session.
Is dotnet-10-csharp-14 safe to install?
It is documentation-only in the skill bundle; review the Security Audits panel on this page for the parent dotfiles package.
SKILL.md
READMESKILL.md - Dotnet 10 Csharp 14
# Anti-Patterns to Avoid ## Quick Reference: What to Use Instead | ❌ Anti-Pattern | ✅ Use Instead | |----------------|----------------| | `new HttpClient()` | Inject `HttpClient` or `IHttpClientFactory` | | `Results.Ok()` | `TypedResults.Ok()` | | Manual Polly config | `AddStandardResilienceHandler()` | | `DateTime.Now` | `DateTime.UtcNow` | | `GetAsync().Result` | `await GetAsync()` | | Exceptions for flow control | `ErrorOr<T>` / Result pattern | | Manual backing fields | C# 14 `field` keyword | | Traditional extension methods | C# 14 extension blocks | | `if (x != null) x.Prop = y` | `x?.Prop = y` (null-conditional assignment) | | Missing `ValidateOnStart()` | Always add `.ValidateOnStart()` | | Singleton → Scoped injection | Use `IServiceScopeFactory` | | `_count++` in singleton | `Interlocked.Increment(ref _count)` | --- ## HttpClient Misuse ```csharp // WRONG: Creates socket exhaustion public async Task Bad() { using var client = new HttpClient(); // Don't instantiate per-request await client.GetAsync("..."); } // CORRECT: Inject IHttpClientFactory or typed client public class MyService(HttpClient client) { public Task<string> GetAsync() => client.GetStringAsync("..."); } // CORRECT: Named client public class MyService(IHttpClientFactory factory) { public async Task<string> GetAsync() { var client = factory.CreateClient("ExternalApi"); return await client.GetStringAsync("..."); } } ``` --- ## DI Captive Dependencies ```csharp // WRONG: Singleton captures scoped service (memory leak) public class SingletonService(IScopedService scoped) { } // CORRECT: Inject IServiceScopeFactory public class SingletonService(IServiceScopeFactory factory) { public async Task DoWork() { await using var scope = factory.CreateAsyncScope(); var scoped = scope.ServiceProvider.GetRequiredService<IScopedService>(); // Use scoped service } } // CORRECT: Use IServiceProvider for optional resolution public class SingletonService(IServiceProvider sp) { public async Task DoWork() { await using var scope = sp.CreateAsyncScope(); var scoped = scope.ServiceProvider.GetRequiredService<IScopedService>(); } } ``` --- ## Exceptions as Flow Control ```csharp // WRONG: Expensive, hard to trace public async Task<IResult> GetUser(int id) { try { var user = await _service.GetUserAsync(id); return TypedResults.Ok(user); } catch (UserNotFoundException) { return TypedResults.NotFound(); } } // CORRECT: Result pattern with ErrorOr public async Task<IResult> GetUser(int id) { var result = await _service.GetUserAsync(id); return result.Match( user => TypedResults.Ok(user), errors => TypedResults.NotFound() ); } // CORRECT: Nullable return public async Task<IResult> GetUser(int id) { var user = await _service.GetUserAsync(id); return user is not null ? TypedResults.Ok(user) : TypedResults.NotFound(); } ``` --- ## Blocking Async ```csharp // WRONG: Deadlock risk var result = GetAsync().Result; var result2 = GetAsync().GetAwaiter().GetResult(); GetAsync().Wait(); // CORRECT: Async all the way var result = await GetAsync(); // If you MUST block (rare), use this pattern var result = Task.Run(() => GetAsync()).GetAwaiter().GetResult(); ``` --- ## N+1 Queries ```csharp // WRONG: N+1 query problem var orders = await db.Orders.ToListAsync(); foreach (var order in orders) { var items = await db.OrderItems.Where(i => i.OrderId == order.Id).ToListAsync(); } // CORRECT: Include related data var orders = await db.Orders .Include(o => o.Items) .ToListAsync(); // CORRECT: Explicit loading when needed var order = await db.Orders.FindAsync(id); await db.Entry(order).Collection(o => o.Items).LoadAsync(); ``` --- ## Async Void ```csharp // WRONG: Exceptions can't be caught public async void HandleEvent(object sender, EventArgs e) { await Proce