dotnet-patterns
OfficialIdiomatic C# and .NET patterns, conventions, dependency injection, async/await, and best practices for building robust, maintainable .NET applications.
What this skill does
When applied, it prepends a system prompt before your request is sent — no extra calls and no change to how you are billed beyond the added tokens.
---
name: dotnet-patterns
description: Idiomatic C# and .NET patterns, conventions, dependency injection, async/await, and best practices for building robust, maintainable .NET applications.
origin: ECC
---
# .NET Development Patterns
Idiomatic C# and .NET patterns for building robust, performant, and maintainable applications.
## When to Activate
- Writing new C# code
- Reviewing C# code
- Refactoring existing .NET applications
- Designing service architectures with ASP.NET Core
## Core Principles
### 1. Prefer Immutability
Use records and init-only properties for data models. Mutability should be an explicit, justified choice.
```csharp
// Good: Immutable value object
public sealed record Money(decimal Amount, string Currency);
// Good: Immutable DTO with init setters
public sealed class CreateOrderRequest
{
public required string CustomerId { get; init; }
public required IReadOnlyList<OrderItem> Items { get; init; }
}
// Bad: Mutable model with public setters
public class Order
{
public string CustomerId { get; set; }
public List<OrderItem> Items { get; set; }
}
```
### 2. Explicit Over Implicit
Be clear about nullability, access modifiers, and intent.
```csharp
// Good: Explicit access modifiers and nullability
public sealed class UserService
{
private readonly IUserRepository _repository;
private readonly ILogger<UserService> _logger;
public UserService(IUserRepository repository, ILogger<UserService> logger)
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<User?> FindByIdAsync(Guid id, CancellationToken cancellationToken)
{
return await _repository.FindByIdAsync(id, cancellationToken);
}
}
```
### 3. Depend on Abstractions
Use interfaces for service boundaries. Register via DI container.
```csharp
// Good: Interface-based dependency
public interface IUse this skill
Add a "skill" field with the skill’s ID to your chat completion request. It is applied server-side before your prompt is sent — no extra calls.
{
"model": "gpt-4o-mini",
"skill": "imp-495339f3-953d-412e-be1f-2cd360c5b985",
"messages": [{ "role": "user", "content": "…" }]
}Install the skill, enable it in your dashboard and (optionally) limit it to specific models. It then applies automatically to every matching request — with no "skill" field to send each time.
Set it up in your dashboardMore skills
Delegate coding work to Codex, Claude Code, or OpenCode as background workers; not simple edits or read-only code lookup.
Create, edit, audit, tidy, validate, or restructure AgentSkills and SKILL.md files.
Search and analyze your own session logs (older/parent conversations) using jq.
Create, view, edit, delete, search, move, or export Apple Notes via the memo CLI on macOS.
Diagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
Set up and use 1Password CLI for sign-in, desktop integration, and reading or injecting secrets.
List, add, edit, complete, or delete Apple Reminders and reminder lists via remindctl.
Create, search, and manage Bear notes via grizzly CLI.