dotnet-10-csharp-14 by mhagrelius/dotfiles
npx skills add https://github.com/mhagrelius/dotfiles --skill dotnet-10-csharp-14.NET 10(长期支持版本,2025年11月)与 C# 14。涵盖最小化 API,不包含 MVC。
官方文档: .NET 10 | C# 14 | ASP.NET Core 10
| 文件 | 主题 |
|---|---|
| csharp-14.md | 扩展块、field 关键字、空条件赋值 |
| minimal-apis.md | 验证、TypedResults、过滤器、模块化单体、垂直切片 |
| security.md | JWT 认证、CORS、速率限制、OpenAPI 安全性、中间件顺序 |
| infrastructure.md |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 选项、弹性、通道、健康检查、缓存、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);
// 核心服务
builder.Services.AddValidation();
builder.Services.AddProblemDetails();
builder.Services.AddOpenApi();
// 安全性
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
builder.Services.AddRateLimiter(opts => { /* 参见 security.md */ });
// 基础设施
builder.Services.AddHealthChecks();
builder.Services.AddOutputCache();
// 模块
builder.Services.AddUsersModule();
var app = builder.Build();
// 中间件(顺序很重要 - 参见 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();
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"];
}
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"];
}
extension<T>(IEnumerable<T> source)
{
public bool IsEmpty => !source.Any();
}
builder.Services.AddValidation();
app.MapPost("/users", (UserDto dto) => TypedResults.Ok(dto));
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;
}
}
builder.Services.AddHttpClient<IApi, ApiClient>()
.AddStandardResilienceHandler();
builder.Services.AddProblemDetails();
app.UseExceptionHandler();
app.UseStatusCodePages();
| 任务 | ✅ 始终使用 | ❌ 绝不使用 |
|---|---|---|
| 扩展成员 | C# 14 extension<T>() 块 | 传统的 this 扩展方法 |
| 属性验证 | C# 14 field 关键字 | 手动后备字段 |
| 空值赋值 | obj?.Prop = value | if (obj != null) obj.Prop = value |
| API 返回 | TypedResults.Ok() | Results.Ok() |
| 选项验证 | .ValidateOnStart() | 缺少验证 |
| HTTP 弹性 | AddStandardResilienceHandler() | 手动 Polly 配置 |
| 时间戳 | DateTime.UtcNow | DateTime.Now |
┌─────────────────────────────────────────────────────────────────┐
│ .NET 10 / C# 14 模式 │
├─────────────────────────────────────────────────────────────────┤
│ 扩展属性: extension<T>(IEnumerable<T> s) { │
│ public bool IsEmpty => !s.Any(); │
│ } │
├─────────────────────────────────────────────────────────────────┤
│ FIELD 关键字: public string Name { │
│ get => field; │
│ set => field = value?.Trim(); │
│ } │
├─────────────────────────────────────────────────────────────────┤
│ 选项验证: .BindConfiguration(Section) │
│ .ValidateDataAnnotations() │
│ .ValidateOnStart(); // 关键! │
├─────────────────────────────────────────────────────────────────┤
│ HTTP 弹性: .AddStandardResilienceHandler(); │
├─────────────────────────────────────────────────────────────────┤
│ 类型化结果: TypedResults.Ok(data) │
│ TypedResults.NotFound() │
│ TypedResults.Created(uri, data) │
├─────────────────────────────────────────────────────────────────┤
│ 错误模式: ErrorOr<User> 或 user?.Match(...) │
├─────────────────────────────────────────────────────────────────┤
│ IOPTIONS: IOptions<T> → 启动时,不重新加载 │
│ IOptionsSnapshot<T> → 每个请求重新加载 │
│ IOptionsMonitor<T> → 实时 + OnChange() │
└─────────────────────────────────────────────────────────────────┘
| 反模式 | 修复方法 |
|---|---|
new HttpClient() | 注入 HttpClient 或 IHttpClientFactory |
Results.Ok() | TypedResults.Ok() |
| 手动 Polly 配置 | AddStandardResilienceHandler() |
| 单例 → 作用域 | 使用 IServiceScopeFactory |
GetAsync().Result | await GetAsync() |
| 使用异常控制流程 | 使用 ErrorOr<T> 结果模式 |
DateTime.Now | DateTime.UtcNow |
缺少 .ValidateOnStart() | 始终添加到选项注册中 |
完整列表请参见 anti-patterns.md。
| 库 | 包 | 用途 |
|---|---|---|
| MediatR | MediatR | CQRS |
| FluentValidation | FluentValidation.DependencyInjectionExtensions | 验证 |
| Mapster | Mapster.DependencyInjection | 映射 |
| ErrorOr | ErrorOr | 结果模式 |
| Polly | Microsoft.Extensions.Http.Resilience | 弹性 |
| Serilog | Serilog.AspNetCore | 日志记录 |
使用示例请参见 libraries.md。
每周安装量
792
代码仓库
GitHub 星标数
2
首次出现
2026年1月21日
安全审计
安装于
codex693
claude-code583
opencode396
github-copilot380
gemini-cli369
amp310
.NET 10 (LTS, Nov 2025) with C# 14. Covers minimal APIs, not MVC.
Official docs: .NET 10 | C# 14 | ASP.NET Core 10
| File | Topics |
|---|---|
| csharp-14.md | Extension blocks, field keyword, null-conditional assignment |
| minimal-apis.md | Validation, TypedResults, filters, modular monolith, vertical slices |
| security.md | JWT auth, CORS, rate limiting, OpenAPI security, middleware order |
| infrastructure.md | Options, resilience, channels, health checks, caching, Serilog, EF Core, keyed services |
| testing.md | WebApplicationFactory, integration tests, auth testing |
| anti-patterns.md | HttpClient, DI captive, blocking async, N+1 queries |
| 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();
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"];
}
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"];
}
extension<T>(IEnumerable<T> source)
{
public bool IsEmpty => !source.Any();
}
builder.Services.AddValidation();
app.MapPost("/users", (UserDto dto) => TypedResults.Ok(dto));
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;
}
}
builder.Services.AddHttpClient<IApi, ApiClient>()
.AddStandardResilienceHandler();
builder.Services.AddProblemDetails();
app.UseExceptionHandler();
app.UseStatusCodePages();
| Task | ✅ ALWAYS Use | ❌ NEVER Use |
|---|---|---|
| Extension members | C# 14 extension<T>() blocks | Traditional this extension methods |
| Property validation | C# 14 field keyword | Manual backing fields |
| Null assignment | obj?.Prop = value | if (obj != null) obj.Prop = value |
| API returns | TypedResults.Ok() |
┌─────────────────────────────────────────────────────────────────┐
│ .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() │
└─────────────────────────────────────────────────────────────────┘
| Anti-Pattern | Fix |
|---|---|
new HttpClient() | Inject HttpClient or IHttpClientFactory |
Results.Ok() | TypedResults.Ok() |
| Manual Polly config | AddStandardResilienceHandler() |
| Singleton → Scoped | Use IServiceScopeFactory |
See anti-patterns.md for complete list.
| Library | Package | Purpose |
|---|---|---|
| MediatR | MediatR | CQRS |
| FluentValidation | FluentValidation.DependencyInjectionExtensions | Validation |
| Mapster | Mapster.DependencyInjection | Mapping |
| ErrorOr | ErrorOr | Result pattern |
| Polly | Microsoft.Extensions.Http.Resilience |
See libraries.md for usage examples.
Weekly Installs
792
Repository
GitHub Stars
2
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex693
claude-code583
opencode396
github-copilot380
gemini-cli369
amp310
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
销售线索筛选框架指南:提升转化率,优化销售流程 | 销售效率工具
760 周安装
hairy-utils:JavaScript/TypeScript 核心工具库 | 异步处理、类型检查、函数式编程
761 周安装
设计系统构建指南:Figma、Airbnb专家框架,助您规模化产品设计
761 周安装
Claude智能体开发指南:创建自主AI助手,掌握agent-development核心技巧
762 周安装
Git 清理工具 - 安全清理本地分支和工作树,智能分类合并与未合并分支
762 周安装
tRPC 端到端类型安全指南 - TypeScript API 开发与 React/Next.js 集成
763 周安装
Results.Ok() |
| Options validation | .ValidateOnStart() | Missing validation |
| HTTP resilience | AddStandardResilienceHandler() | Manual Polly configuration |
| Timestamps | DateTime.UtcNow | DateTime.Now |
GetAsync().Resultawait GetAsync() |
| Exceptions for flow | Use ErrorOr<T> Result pattern |
DateTime.Now | DateTime.UtcNow |
Missing .ValidateOnStart() | Always add to Options registration |
| Resilience |
| Serilog | Serilog.AspNetCore | Logging |