| name | dotnet-csharp-code-smells |
| category | fundamentals |
| subcategory | diagnostics |
| description | Detects C# code smells during review. Anti-patterns, async misuse, DI mistakes, fixes. |
| license | MIT |
| targets | ["*"] |
| tags | ["csharp","dotnet","skill"] |
| version | 0.0.1 |
| author | dotnet-agent-harness |
| invocable | true |
| claudecode | {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} |
| codexcli | {"short-description":".NET skill guidance for csharp tasks"} |
| opencode | {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} |
| copilot | {} |
| geminicli | {} |
| antigravity | {} |
dotnet-csharp-code-smells
Proactive code-smell and anti-pattern detection for C# code. This skill triggers during all workflow modes -- planning,
implementation, and review. Each entry identifies the smell, explains why it is harmful, provides the correct fix, and
references the relevant CA rule or cross-reference.
Scope
- Resource management (IDisposable misuse)
- Async anti-patterns and deadlock detection
- DI lifetime misuse and captive dependencies
- Null-handling mistakes and NRT violations
- LINQ pitfalls and string handling issues
Out of scope
- LLM-specific generation mistakes (wrong NuGet packages, MSBuild errors) -- see [skill:dotnet-agent-gotchas]
- SOLID/DRY design principles -- see [skill:dotnet-solid-principles]
- Naming and style conventions -- see [skill:dotnet-csharp-coding-standards]
Cross-references: [skill:dotnet-csharp-async-patterns] for async gotchas, [skill:dotnet-csharp-coding-standards] for
naming and style, [skill:dotnet-csharp-dependency-injection] for DI lifetime misuse,
[skill:dotnet-csharp-nullable-reference-types] for NRT annotation mistakes.
1. Resource Management (IDisposable Misuse)
| Smell | Why Harmful | Fix | Rule |
|---|
Missing using on disposable locals | Leaks unmanaged handles (sockets, files, DB connections) | Wrap in using declaration or using block | CA2000 |
Undisposed IDisposable fields | Class holds disposable resource but never disposes it | Implement IDisposable; dispose fields in Dispose() | CA2213 |
| Wrong Dispose pattern (no finalizer guard) | Double-dispose or missed cleanup on GC finalization | Follow canonical Dispose(bool) pattern; call GC.SuppressFinalize(this) | CA1816 |
| Disposable created in one method, stored in field | Ownership unclear; easy to forget disposal | Document ownership; make the containing class IDisposable | CA2000 |
using on non-owned resource | Premature disposal of shared resource (e.g., injected HttpClient) | Only dispose resources you create; let DI manage injected services |