csharp-idioms
irahardianto/awesome-agv/.agents/skills/csharp-idioms/SKILL.md
Modern C# (10+/.NET) coding idioms: nullable reference types, records, pattern matching, async/await with CancellationTokens, LINQ performance, and DI. Use when writing, modifying, or reviewing C# application code or domain models. Pair with dotnet-idioms for framework APIs.
Skill157 starsChanged 43 days ago
What's in it
- C# Idioms and Patterns
- Modern C# Features (10+)
- Error Handling
- Async/Await
- Dependency Injection
- LINQ
- Naming
- Testing
- Formatting and Static Analysis
- Related
---
name: csharp-idioms
description: >-
Modern C# (10+/.NET) coding idioms: nullable reference types, records, pattern matching, async/await with CancellationTokens, LINQ performance, and DI. Use when writing, modifying, or reviewing C# application code or domain models. Pair with dotnet-idioms for framework APIs.
---
## C# Idioms and Patterns
C# rewards type safety, LINQ expressiveness, and async-first design. Modern C# (10+/.NET 6+) favors records, nullable reference types, and minimal APIs. Idiomatic C# = clean, async-aware, framework-integrated.
> Scope: C# coding idioms. Test naming: .agents/rules/testing-strategy.md. Logging: `@.agents/skills/logging-implementation/SKILL.md`.
### Modern C# Features (10+)
1. **Nullable reference types — always enabled:**
```csharp
// ✅ Explicit nullability
public Task? FindById(string id) { ... }
public Task GetById(string id) { ... } // never returns null — throws
// In .csproj: <Nullable>enable</Nullable>
```
2. **Records for immutable data:**
```csharp
public record CreateTaskRequest(string Title, Priority Priority);
public record TaskResponse(string Id, string Title, DateTime CreatedAt);
```
3. **Pattern matching:**
```csharp
return result switch
{
Success(var task) => Ok(task),
NotFound(var id) => NotFound($"Task {id} not found"),
ValidationError(var errors) => BadRequest(errors),
_ => StatusCode(500)
};
```
4. **`required` and `init` for safe construction:**
```csharp
public class AppConfig
{
public required string DatabaseUrl { get; init; }
public required string ApiKey { get; init; }
public int MaxRetries { get; init; } = 3;
}
```
### Error Handling
1. **Result pattern over exceptions for expected failures:**
```csharp
public record Result<T>
{
public T? Value { get; init; }
public string? Error { get; init; }
public bool IsSuccess => Error is null;
public static Result<T> Ok(T value) => new() { Value = value };
public static Result<T> Fail(string error) => new() { Error = error };
}
```
2. **Domain exceptions for unexpected failures — never raw `Exception`.**
3. **Never `catch (Exception)` without re-throw or specific handling.**
### Async/Await
1. **Async all the way — never `.Result` or `.Wait()` on tasks:**
```csharp
// ✅ Async pipeline
public async Task<Task> GetTaskAsync(string id, CancellationToken ct)
{
return await _storage.GetByIdAsync(id, ct)
?? throw new NotFoundException("Task", id);
}
// ❌ Sync-over-async — deadlock risk
var task = _storage.GetByIdAsync(id).Result;
```
2. **Always accept `CancellationToken`** on async methods.
3. **`ConfigureAwait(false)`** in library code only.
### Dependency Injection
1. **Constructor injection — no property or method injection:**
```csharp
public class TaskService
{
private readonly ITaskStorage _storage;
private readonly ILogger<TaskService> _logger;
public TaskService(ITaskStorage storage, ILogger<TaskService> logger)
{
_storage = storage;
_logger = logger;
}
}
```
2. **Register in DI container — never `new` a service:**
```csharp
builder.Services.AddScoped<ITaskStorage, PostgresTaskStorage>();
builder.Services.AddScoped<TaskService>();
```
### LINQ
1. **Prefer method syntax for complex queries, query syntax for joins:**
```csharp
var active = tasks
.Where(t => t.IsActive)
.OrderByDescending(t => t.Priority)
.Select(t => new TaskSummary(t.Id, t.Title));
```
2. **Never mutate collections during LINQ iteration.**
### Naming
1. **PascalCase** for classes, methods, properties, events, namespaces.
2. **camelCase** for parameters, local variables.
3. **`_camelCase`** for private fields (prefix underscore).
4. **`I` prefix** for interfaces: `ITaskStorage`.
5. **`Async` suffix** for async methods: `GetByIdAsync`.
### Testing
1. **xUnit + FluentAssertions:**
```csharp
[Fact]
public async Task GetTask_ReturnsTask_WhenExists()
{
var result = await _service.GetTaskAsync("task-1", CancellationToken.None);
result.Should().NotBeNull();
result.Title.Should().Be("Test Task");
}
```
2. **`[Theory]` for parameterized tests:**
```csharp
[Theory]
[InlineData("low", 1)]
[InlineData("medium", 5)]
[InlineData("high", 10)]
public void PriorityScore_MapsCorrectly(string priority, int expected)
{
Priority.Score(priority).Should().Be(expected);
}
```
3. **NSubstitute or Moq for mocking.**
### Formatting and Static Analysis
| Tool | Purpose | Command |
|---|---|---|
| `dotnet format` | Canonical formatting | `dotnet format` |
| Roslyn Analyzers | Compile-time analysis | Built-in |
| `SonarAnalyzer` | Comprehensive analysis | NuGet package |
| `dotnet-outdated` | Dependency freshness | `dotnet-outdated` |
| `dotnet list package --vulnerable` | CVE scanning | Built-in (.NET 8+) |
### Related
- Code Idioms and Conventions .agents/rules/code-idioms-and-conventions.md
- Testing Strategy .agents/rules/testing-strategy.md
- Error Handling Principles .agents/rules/error-handling-principles.md
- Dependency Management Principles @.agents/rules/dependency-management-principles.md
More agent context in irahardianto/awesome-agv
59 other files this repository gives its agents.
AGENTS.md
Skill
- adr.agents/skills/adr/SKILL.md
- agent-protocols.agents/skills/agent-protocols/SKILL.md
- angular-idioms.agents/skills/angular-idioms/SKILL.md
- api-documentation.agents/skills/api-documentation/SKILL.md
- axum-idioms.agents/skills/axum-idioms/SKILL.md
- browser-automation.agents/skills/browser-automation/SKILL.md
- chaos-testing.agents/skills/chaos-testing/SKILL.md
- ci-cd.agents/skills/ci-cd/SKILL.md
- cli-development.agents/skills/cli-development/SKILL.md
- code-audit.agents/skills/code-audit/SKILL.md
- code-review.agents/skills/code-review/SKILL.md
- cpp-idioms.agents/skills/cpp-idioms/SKILL.md
- data-engineering.agents/skills/data-engineering/SKILL.md
- debugging-protocol.agents/skills/debugging-protocol/SKILL.md
- django-idioms.agents/skills/django-idioms/SKILL.md
- dotnet-idioms.agents/skills/dotnet-idioms/SKILL.md
- elixir-idioms.agents/skills/elixir-idioms/SKILL.md
- embedded-systems.agents/skills/embedded-systems/SKILL.md
- feature-flags.agents/skills/feature-flags/SKILL.md
- flutter-idioms.agents/skills/flutter-idioms/SKILL.md
- frontend-design.agents/skills/frontend-design/SKILL.md
- git-commit-integrity.agents/skills/git-commit-integrity/SKILL.md
- go-idioms.agents/skills/go-idioms/SKILL.md
- guardrails.agents/skills/guardrails/SKILL.md
- hono-idioms.agents/skills/hono-idioms/SKILL.md
- incident-response.agents/skills/incident-response/SKILL.md
- java-idioms.agents/skills/java-idioms/SKILL.md
- javascript-idioms.agents/skills/javascript-idioms/SKILL.md
- kotlin-idioms.agents/skills/kotlin-idioms/SKILL.md
- laravel-idioms.agents/skills/laravel-idioms/SKILL.md
- logging-implementation.agents/skills/logging-implementation/SKILL.md
- ml-engineering.agents/skills/ml-engineering/SKILL.md
- mobile-design.agents/skills/mobile-design/SKILL.md
- mobile-testing.agents/skills/mobile-testing/SKILL.md
- nextjs-idioms.agents/skills/nextjs-idioms/SKILL.md
- parallel-dispatch.agents/skills/parallel-dispatch/SKILL.md
- payment-integration.agents/skills/payment-integration/SKILL.md
- perf-optimization.agents/skills/perf-optimization/SKILL.md
- php-idioms.agents/skills/php-idioms/SKILL.md
- postgres-idioms.agents/skills/postgres-idioms/SKILL.md
- python-idioms.agents/skills/python-idioms/SKILL.md
- rails-idioms.agents/skills/rails-idioms/SKILL.md
- react-idioms.agents/skills/react-idioms/SKILL.md
- refactoring-patterns.agents/skills/refactoring-patterns/SKILL.md
- research-methodology.agents/skills/research-methodology/SKILL.md
- ruby-idioms.agents/skills/ruby-idioms/SKILL.md
- rust-idioms.agents/skills/rust-idioms/SKILL.md
- security-audit.agents/skills/security-audit/SKILL.md
- sequential-thinking.agents/skills/sequential-thinking/SKILL.md
- spring-boot-idioms.agents/skills/spring-boot-idioms/SKILL.md
- sql-idioms.agents/skills/sql-idioms/SKILL.md
- structured-spec.agents/skills/structured-spec/SKILL.md
- supply-chain-security.agents/skills/supply-chain-security/SKILL.md
- swift-idioms.agents/skills/swift-idioms/SKILL.md
- testability-patterns.agents/skills/testability-patterns/SKILL.md
- testing-strategy.agents/skills/testing-strategy/SKILL.md
- typescript-idioms.agents/skills/typescript-idioms/SKILL.md
- vue-idioms.agents/skills/vue-idioms/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
No reports yet. Be the first to say whether it worked.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool public_context_discussion, action report. How to connect one.

