dotnet-10-csharp-14 について
.NET 10 & C# 14 Best Practicesは、ASP.NET Coreのminimal APIを開発する人向けのリファレンススキルです。言語機能、API設計、セキュリティ、インフラ、テスト、ライブラリ、アンチパターンの指針をまとめています。
主な機能
- 01C# 14の言語ガイダンス
- 02Minimal APIの設計パターン
- 03セキュリティとインフラの実践
- 04テストとライブラリの参考情報
- 05判断フローチャートとアンチパターン
活用シーン
- 01.NET 10 minimal APIの計画
- 02エラー処理やオプションのパターン選択
- 03セキュリティとレジリエンス設定の確認
- 04C#と.NETでよくある落とし穴の回避
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mhagrelius/ dotfiles --skill dotnet-10-csharp-14インストール後、Claude Code で/dotnet-10-csharp-14を入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
anti-patterns.mdcsharp-14.mdinfrastructure.mdlibraries.mdminimal-apis.mdsecurity.mdtesting.md詳細
.NET 10 と C# 14 のベストプラクティス
.NET 10(LTS、2025 年 11 月)と C# 14 を対象としています。MVC ではなく、Minimal API を扱います。
公式ドキュメント: .NET 10 | C# 14 | ASP.NET Core 10
詳細ファイル
| ファイル | トピック |
|---|---|
| csharp-14.md | 拡張ブロック、field キーワード、null 条件付き代入 |
| minimal-apis.md | 検証、TypedResults、フィルター、モジュラーモノリス、垂直スライス |
| security.md | JWT 認証、CORS、レート制限、OpenAPI セキュリティ、ミドルウェアの順序 |
| infrastructure.md | Options、レジリエンス、チャネル、ヘルスチェック、キャッシュ、Serilog、EF Core、キー付きサービス |
| testing.md | WebApplicationFactory、統合テスト、認証テスト |
| anti-patterns.md | HttpClient、DI のキャプティブ依存、同期的な非同期処理、N+1 クエリ |
| libraries.md | MediatR、FluentValidation、Mapster、ErrorOr、Polly、Aspire |
クイックスタート
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>14</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
var builder = WebApplication.CreateBuilder(args);
// Core services
builder.Services.AddValidation();
builder.Services.AddProblemDetails();
builder.Services.AddOpenApi();
// Security
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
builder.Services.AddRateLimiter(opts => { /* see security.md */ });
// Infrastructure
builder.Services.AddHealthChecks();
builder.Services.AddOutputCache();
// Modules
builder.Services.AddUsersModule();
var app = builder.Build();
// Middleware (ORDER MATTERS - see security.md)
app.UseExceptionHandler();
app.UseHttpsRedirection();
app.UseCors();
app.UseRateLimiter();
app.UseAuthentication();
app.UseAuthorization();
app.UseOutputCache();
app.MapOpenApi();
app.MapHealthChecks("/health");
app.MapUsersEndpoints();
app.Run();
判断フローチャート
Result と例外の比較
digraph {
"Error type?" [shape=diamond];
"Expected?" [shape=diamond];
"Result<T>/ErrorOr" [shape=box];
"Exception" [shape=box];
"Error type?" -> "Expected?" [label="domain"];
"Error type?" -> "Exception" [label="infrastructure"];
"Expected?" -> "Result<T>/ErrorOr" [label="yes"];
"Expected?" -> "Exception" [label="no"];
}
IOptions の選択
digraph {
"Runtime changes?" [shape=diamond];
"Per-request?" [shape=diamond];
"IOptions<T>" [shape=box];
"IOptionsSnapshot<T>" [shape=box];
"IOptionsMonitor<T>" [shape=box];
"Runtime changes?" -> "IOptions<T>" [label="no"];
"Runtime changes?" -> "Per-request?" [label="yes"];
"Per-request?" -> "IOptionsSnapshot<T>" [label="yes"];
"Per-request?" -> "IOptionsMonitor<T>" [label="no"];
}
チャネルの種類
digraph {
"Trust producer?" [shape=diamond];
"Can drop?" [shape=diamond];
"Bounded+Wait" [shape=box,style=filled,fillcolor=lightgreen];
"Bounded+Drop" [shape=box];
"Unbounded" [shape=box];
"Trust producer?" -> "Unbounded" [label="yes"];
"Trust producer?" -> "Can drop?" [label="no"];
"Can drop?" -> "Bounded+Drop" [label="yes"];
"Can drop?" -> "Bounded+Wait" [label="no"];
}
主なパターンの概要
C# 14 の拡張ブロック
extension<T>(IEnumerable<T> source)
{
public bool IsEmpty => !source.Any();
}
.NET 10 の組み込み検証
builder.Services.AddValidation();
app.MapPost("/users", (UserDto dto) => TypedResults.Ok(dto));
TypedResults(必ず使用)
app.MapGet("/users/{id}", async (int id, IUserService svc) =>
await svc.GetAsync(id) is { } user
? TypedResults.Ok(user)
: TypedResults.NotFound());
モジュールパターン
public static class UsersModule
{
public static IServiceCollection AddUsersModule(this IServiceCollection s) => s
.AddScoped<IUserService, UserService>();
public static IEndpointRouteBuilder MapUsersEndpoints(this IEndpointRouteBuilder app)
{
var g = app.MapGroup("/api/users").WithTags("Users");
g.MapGet("/{id}", GetUser.Handle);
return app;
}
}
HTTP レジリエンス
builder.Services.AddHttpClient<IApi, ApiClient>()
.AddStandardResilienceHandler();
エラー処理(RFC 9457)
builder.Services.AddProblemDetails();
app.UseExceptionHandler();
app.UseStatusCodePages();
必須パターン(必ず使用してください)
| タスク | ✅ 必ず使用 | ❌ 絶対に使用しない |
|---|---|---|
| 拡張メンバー | C# 14 の extension<T>() ブロック | 従来の this 拡張メソッド |
| プロパティの検証 | C# 14 の field キーワード | 手動のバッキングフィールド |
| null の代入 | obj?.Prop = value | if (obj != null) obj.Prop = value |
| API の戻り値 | TypedResults.Ok() | Results.Ok() |
| Options の検証 | .ValidateOnStart() | 検証の省略 |
| HTTP レジリエンス | AddStandardResilienceHandler() | 手動の Polly 設定 |
| タイムスタンプ | DateTime.UtcNow | DateTime.Now |
クイックリファレンスカード
┌─────────────────────────────────────────────────────────────────┐
│ .NET 10 / C# 14 PATTERNS │
├─────────────────────────────────────────────────────────────────┤
│ EXTENSION PROPERTY: extension<T>(IEnumerable<T> s) { │
│ public bool IsEmpty => !s.Any(); │
│ } │
├─────────────────────────────────────────────────────────────────┤
│ FIELD KEYWORD: public string Name { │
│ get => field; │
│ set => field = value?.Trim(); │
│ } │
├─────────────────────────────────────────────────────────────────┤
│ OPTIONS VALIDATION: .BindConfiguration(Section) │
│ .ValidateDataAnnotations() │
│ .ValidateOnStart(); // CRITICAL! │
├─────────────────────────────────────────────────────────────────┤
│ HTTP RESILIENCE: .AddStandardResilienceHandler(); │
├─────────────────────────────────────────────────────────────────┤
│ TYPED RESULTS: TypedResults.Ok(data) │
│ TypedResults.NotFound() │
│ TypedResults.Created(uri, data) │
├─────────────────────────────────────────────────────────────────┤
│ ERROR PATTERN: ErrorOr<User> or user?.Match(...) │
├─────────────────────────────────────────────────────────────────┤
│ IOPTIONS: IOptions<T> → startup, no reload │
│ IOptionsSnapshot<T> → per-request reload │
│ IOptionsMonitor<T> → live + OnChange() │
└─────────────────────────────────────────────────────────────────┘
アンチパターンのクイックリファレンス
| アンチパターン | 修正方法 |
|---|---|
new HttpClient() | HttpClient または IHttpClientFactory を注入する |
Results.Ok() | TypedResults.Ok() |
| Polly の手動設定 | AddStandardResilienceHandler() |
| Singleton → Scoped | IServiceScopeFactory を使用する |
GetAsync().Result | await GetAsync() |
| フロー制御に例外を使用 | ErrorOr<T> の Result パターンを使用する |
DateTime.Now | DateTime.UtcNow |
.ValidateOnStart() の不足 | Options の登録に必ず追加する |
完全な一覧は anti-patterns.md を参照してください。
ライブラリのクイックリファレンス
| ライブラリ | パッケージ | 用途 |
|---|---|---|
| MediatR | MediatR | CQRS |
| FluentValidation | FluentValidation.DependencyInjectionExtensions | 検証 |
| Mapster | Mapster.DependencyInjection | マッピング |
| ErrorOr | ErrorOr | Result パターン |
| Polly | Microsoft.Extensions.Http.Resilience | レジリエンス |
| Serilog | Serilog.AspNetCore | ロギング |
使用例は libraries.md を参照してください。
コメント
Markdown 対応