Skip to content
Skills Library
Programming · Building & coding

csharp

/csharp

Apply these opinionated C# conventions whenever writing or reviewing C# 12 / .NET 8+ code: nullable enabled with warnings as errors, records and primary constructors, pattern matching over cast chains, the Result pattern for expected failures, async all the way with CancellationToken, IOptions config, IHttpClientFactory, and never returning EF entities from an API.

Licence
MIT
Last repository change
23.10.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
1
Scripts
0
HTML comments
0
URLs in SKILL.md
0
Deprecation

No signals detected. Repository changed on 23.10.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Apply these opinionated C# conventions whenever writing or reviewing C# 12 / .NET 8+ code: nullable enabled with warnings as errors, records and primary constructors, pattern matching over cast chains, the Result pattern for expected failures, async all the way with CancellationToken, IOptions config, IHttpClientFactory, and never returning EF entities from an API.

Original author description

Apply these opinionated C# conventions whenever writing or reviewing C# 12 / .NET 8+ code: nullable enabled with warnings as errors, records and primary constructors, pattern matching over cast chains, the Result pattern for expected failures, async all the way with CancellationToken, IOptions config, IHttpClientFactory, and never returning EF entities from an API.

How it works

  1. Conventions
Original SKILL.md headings · 35 lines, 515 words
SKILL.md preview
---
name: csharp
description: "Apply these opinionated C# conventions whenever writing or reviewing C# 12 / .NET 8+ code: nullable enabled with warnings as errors, records and primary constructors, pattern matching over cast chains, the Result pattern for expected failures, async all the way with CancellationToken, IOptions config, IHttpClientFactory, and never returning EF entities from an API."
---

# C# Conventions

House conventions for C# 12 / .NET 8+. Apply them to code you are writing or changing — don't rewrite untouched files to match unless asked.

## Conventions

- **`<Nullable>enable</Nullable>` and warnings as errors.** The nullable annotations only pay off if the warnings block the build; ignored, they become decoration that lies about which references can be null.
- **C# 12 defaults:** file-scoped namespaces, primary constructors, collection expressions, `required` members. Records for DTOs and value objects — value equality is what you want when comparing data, and hand-written `Equals`/`GetHashCode` pairs drift apart.
- **Pattern matching over type-test-and-cast chains.** Switch expressions on a closed hierarchy let the compiler warn about unhandled cases; an `if`/`else if` ladder just falls through silently when a new type appears.
- **Result pattern for expected failures**, exceptions for genuinely exceptional ones. "Not found" and "invalid input" are ordinary outcomes and belong in the return type where the caller must deal with them; using exceptions for control flow hides them from the signature and costs a stack unwind per occurrence. A closed record hierarchy gives you exhaustive `switch` over the outcomes:

  ```csharp
  public abstract record Result<T>
  {
      public sealed record Ok(T Value) : Result<T>;
      public sealed record Fail(string Error) : Result<T>;
  }

  var message = GetUser(id) switch
  {
      Result<User>.Ok(var user) => $"Found {user.Name}",
      Result<User>.Fail(var error) => error,
  };
  ```

- **Async all the way down.** `.Result` and `.Wait()` deadlock under a synchronisation context and burn a thread pool thread everywhere else. If a call chain has to be async at the bottom, it is async at the top.
- **Accept and pass a `CancellationToken` on every async public method.** Without it a cancelled request keeps its database query and HTTP call running to completion, and the work is charged to a caller who has already gone.
- **Never expose EF entities from an API.** Project to a DTO with `Select` — otherwise you ship whatever the schema grows next, and lazy loading turns serialisation into an N+1 query storm.
- **EF specifics that show up as production incidents rather than test failures:** `AsNoTracking()` on every read-only query, since change tracking on a large result set is pure overhead; `AsSplitQuery()` when `Include`-ing more than one collection, because a single join multiplies rows cartesian-style; `ExecuteUpdateAsync`/`ExecuteDeleteAsync` (.NET 7+) for bulk changes rather than loading entities to modify them; a global `HasQueryFilter` for soft deletes so no query can forget the flag.
- **Keyed services when one interface has several implementations** (.NET 8): register with `AddKeyedScoped<INotifier, EmailNotifier>("email")` and resolve with `[FromKeyedServices("email")]`. It beats an enum-switching factory because the container still owns the lifetimes.
- **`IOptions<T>` with validated, strongly-typed config.** `configuration["Some:Key"]` fails at the call site, at runtime, on a typo. A bound options class with `ValidateOnStart` fails at boot with the field named.
- **`IHttpClientFactory`, never `new HttpClient()` per call** — socket exhaustion from lingering TIME_WAIT connections is the classic failure, and it only appears under load.
- **`Span<T>`/`Memory<T>` and pooling where a profiler says allocations matter.** They complicate the code, so spend that complexity where there is a measurement, not on principle.

Versions

RepositoryScoreLicence
This page · alexander-danilenko/cortex-claude-code-plugins100MIT
G1Joshi/Agent-Skills100MIT
pingqLIN/skill-096MIT
claude-dev-suite/claude-dev-suite95MIT

Database snapshot: 13.11.2026 · package version 49e9fd341e7a (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100csharp-idioms
    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.
  • 87csharp-conventions
    Modern C# idioms for any .NET project (C# 10+, .NET 6+): nullable reference types, records, readonly structs, primary constructors, pattern matching, async/await with CancellationToken, IDisposable/IAsyncDisposable, file-scoped namespaces, var usage, naming conventions…
  • 90neo-csharp
    Use this skill when writing, reviewing, debugging, or modernizing C# code in .NET projects. Trigger for .cs/.csproj files, C# language-version questions, nullable reference types, records, pattern matching, async/cancellation, or version-appropriate syntax from C# 10+.
  • 100programming-csharp
    Modern C# and .NET practices for AI coding agents: nullable contracts, async ownership, data access, failure handling. Use when writing .NET code.
  • 100csharp-dotnet
    Use when building on .NET 8+ with C# 12. Covers nullable reference types, records, async/await correctness, minimal APIs, dependency injection, and EF Core query performance. Trigger on "async deadlock in my asp.net app", "turn on nullable reference types", "ef core is doing n+1…
  • 100csharp-conventions
    General C# coding conventions covering latest language features (C# 13), nullable reference types, naming conventions, formatting rules, exception handling, project structure, data access patterns, validation, and structured logging. Apply this skill whenever writing, reviewing,…

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.