dotnet-best-practices
2
总安装量
2
周安装量
#64153
全站排名
安装命令
npx skills add https://github.com/akires47/agent-skills --skill dotnet-best-practices
Agent 安装分布
opencode
1
cursor
1
claude-code
1
Skill 文档
.NET Best Practices
Comprehensive development guide for modern .NET applications with C# 12+. Contains 100+ rules across 11 categories, prioritized by impact to guide code generation, refactoring, and reviews.
When to Apply
Reference these guidelines when:
- Writing new C# code or refactoring existing code
- Designing APIs, services, or domain models
- Implementing data access layers or async operations
- Reviewing code for performance, correctness, or maintainability
- Setting up dependency injection, configuration, or logging
- Writing tests (unit, integration, snapshot)
- Building distributed systems or microservices
Rule Categories by Priority
| Priority | Category | Impact | Prefix | Rules |
|---|---|---|---|---|
| 1 | Error Handling | CRITICAL | error- |
8 |
| 2 | Async Patterns | CRITICAL | async- |
9 |
| 3 | Type Design | HIGH | type- |
10 |
| 4 | Database Performance | HIGH | db- |
12 |
| 5 | API Design | MEDIUM-HIGH | api- |
8 |
| 6 | Dependency Injection | MEDIUM | di- |
7 |
| 7 | Architecture | MEDIUM | arch- |
8 |
| 8 | Serialization | MEDIUM | serial- |
6 |
| 9 | Performance | LOW-MEDIUM | perf- |
12 |
| 10 | Logging | LOW-MEDIUM | log- |
6 |
| 11 | Testing | LOW | test- |
8 |
Total: 94 Rules
Quick Reference
1. Error Handling (CRITICAL)
error-result-pattern– Return Result for expected errors, not exceptionserror-validation-boundaries– Validate at handler entry points, fail fasterror-guard-clauses– Use guard clauses for null/range checkserror-exception-filters– Usecatch whenfor selective exception handlingerror-global-handlers– Implement middleware for unhandled exceptionserror-never-catch-all– Avoid catching all exceptions without rethrowingerror-custom-exceptions– Use built-in exceptions, avoid custom oneserror-exception-properties– Add context to exceptions via Data property
2. Async Patterns (CRITICAL)
async-cancellation-token– Always accept CancellationToken in async methodsasync-all-the-way– Never block on async code with .Result or .Wait()async-valuetask– Use ValueTask for hot paths with synchronous completionsasync-iasyncenumerable– Use IAsyncEnumerable for streaming dataasync-parallel-foreach– Use Parallel.ForEachAsync for bounded concurrencyasync-channel– Use System.Threading.Channels for producer-consumerasync-semaphore– Use SemaphoreSlim for rate limitingasync-configureawait– Use ConfigureAwait(false) in library codeasync-avoid-async-void– Never use async void except for event handlers
3. Type Design (HIGH)
type-records-for-dtos– Use records for immutable DTOstype-readonly-record-struct– Use readonly record struct for value objectstype-seal-classes– Seal classes by default unless designed for inheritancetype-composition-over-inheritance– Prefer composition over inheritancetype-nullable-reference-types– Enable nullable reference types, handle nulls explicitlytype-pattern-matching– Use switch expressions and pattern matchingtype-primary-constructors– Use primary constructors for simple classestype-immutability-default– Design types to be immutable by defaulttype-explicit-conversions– Avoid implicit conversions for value objectstype-no-public-setters– Use init or constructor, not public setters
4. Database Performance (HIGH)
db-read-write-separation– Separate read models from write modelsdb-notracking-default– Configure NoTracking by default in EF Coredb-row-limits– Always apply row limits to queriesdb-n-plus-one– Avoid N+1 queries with Include or batch fetchingdb-cartesian-explosion– Use AsSplitQuery to prevent Cartesian productsdb-compiled-queries– Use EF.CompileAsyncQuery for hot pathsdb-connection-pooling– Use NpgsqlDataSource for connection poolingdb-optimistic-concurrency– Use RowVersion for concurrent updatesdb-projections-over-entities– Use Select projections, not full entitiesdb-no-application-joins– Do joins in SQL, never in application codedb-bulk-operations– Use ExecuteUpdate/Delete for bulk modificationsdb-no-generic-repositories– Use purpose-built stores, not generic repositories
5. API Design (MEDIUM-HIGH)
api-accept-abstractions– Accept IEnumerable/IReadOnlyCollection in parametersapi-return-specific-types– Return IReadOnlyList/IReadOnlyCollection from methodsapi-readonly-collections– Return immutable collections from public APIsapi-method-overloads– Use overloads for common scenarios, not optionalsapi-extension-methods– Use extension methods for fluent APIsapi-fluent-builders– Use builder pattern for complex object constructionapi-async-suffix– Suffix async methods with Asyncapi-avoid-out-params– Return tuples or records instead of out parameters
6. Dependency Injection (MEDIUM)
di-extension-methods– Group service registrations in extension methodsdi-lifetime-management– Understand Singleton, Scoped, Transient lifetimesdi-options-pattern– Use IOptions for configurationdi-validate-on-start– Call ValidateOnStart() for configuration validationdi-keyed-services– Use keyed services for multiple implementationsdi-avoid-service-locator– Never inject IServiceProvider as service locatordi-no-scoped-in-singleton– Never inject Scoped services into Singleton
7. Architecture (MEDIUM)
arch-vertical-slice– Organize by feature (vertical slices), not layersarch-feature-organization– One feature per file with all related codearch-static-handlers– Use static handler methods in featuresarch-module-boundaries– Use InternalsVisibleTo for module boundariesarch-feature-flags– Implement runtime feature togglingarch-background-services– Use IHostedService for background workarch-minimal-apis– Prefer minimal APIs over controller-based APIsarch-map-endpoints-per-feature– Each feature maps its own endpoints
8. Serialization (MEDIUM)
serial-system-text-json– Use System.Text.Json, not Newtonsoft.Jsonserial-source-generators– Use JsonSerializerContext source generatorsserial-protobuf– Use Protobuf for actor systems and event sourcingserial-messagepack– Use MessagePack for high-performance scenariosserial-wire-compatibility– Design for forward/backward compatibilityserial-no-type-names– Never embed type names in wire format
9. Performance (LOW-MEDIUM)
perf-span-and-memory– Use Span/Memory for buffer operationsperf-defer-enumeration– Don’t materialize IEnumerable until necessaryperf-frozen-collections– Use FrozenDictionary/FrozenSet for static dataperf-string-interpolation– Use string interpolation, not concatenationperf-list-capacity– Initialize List with capacity when size is knownperf-dictionary-trygetvalue– Use TryGetValue instead of ContainsKey + indexerperf-array-pool– Use ArrayPool for temporary large buffersperf-object-pool– Use ObjectPool for expensive-to-create objectsperf-compiled-regex– Use GeneratedRegex source generatorperf-static-pure-functions– Prefer static methods for pure functionsperf-stackalloc– Use stackalloc for small temporary buffersperf-avoid-closure-allocations– Cache delegates to avoid closure allocations
10. Logging (LOW-MEDIUM)
log-structured-logging– Use structured logging with named parameterslog-logger-message-define– Use LoggerMessage.Define for high-performance logginglog-correlation-ids– Implement request correlation via Activity.Currentlog-activity-tracing– Use System.Diagnostics.Activity for distributed tracinglog-log-levels– Use appropriate log levels (Trace/Debug/Info/Warning/Error/Critical)log-avoid-string-interpolation– Pass message template, not interpolated strings
11. Testing (LOW)
test-testcontainers– Use TestContainers for integration tests, not mockstest-snapshot-testing– Use Verify for snapshot testing APIs and outputstest-arrange-act-assert– Follow AAA pattern for test structuretest-fakes-vs-mocks– Prefer hand-written fakes over mocking librariestest-data-builders– Use builder pattern for complex test datatest-integration-webappfactory– Use WebApplicationFactory for API integration teststest-one-assertion-per-test– Focus each test on a single assertiontest-descriptive-names– Use descriptive test names that explain the scenario
How to Use
Read individual rule files for detailed explanations and code examples:
rules/error-result-pattern.md
rules/async-cancellation-token.md
rules/db-notracking-default.md
Each rule file contains:
- Brief explanation of why it matters
- â Incorrect code example with explanation
- â Correct code example with explanation
- Additional context and references
Full Compiled Document
For the complete guide with all rules expanded inline: AGENTS.md
This document is optimized for LLM context loading and contains all rules with full code examples.
Anti-Patterns Summary
Common mistakes to avoid:
| Anti-Pattern | Rule |
|---|---|
| Throwing exceptions for business logic | error-result-pattern |
| Blocking on async code with .Result | async-all-the-way |
| Mutable DTOs with public setters | type-records-for-dtos |
| Queries without row limits | db-row-limits |
| N+1 query problems | db-n-plus-one |
| Returning List from APIs | api-readonly-collections |
| Massive Program.cs with 200+ DI registrations | di-extension-methods |
| Organizing by technical layers | arch-vertical-slice |
| Using Newtonsoft.Json | serial-system-text-json |
| String concatenation in loops | perf-string-interpolation |
| Mocking databases in tests | test-testcontainers |
Resources
- .NET Documentation: https://learn.microsoft.com/en-us/dotnet/
- C# Language Reference: https://learn.microsoft.com/en-us/dotnet/csharp/
- EF Core Performance: https://learn.microsoft.com/en-us/ef/core/performance/
- ASP.NET Core: https://learn.microsoft.com/en-us/aspnet/core/
- Performance Best Practices: https://learn.microsoft.com/en-us/dotnet/standard/performance/