Skip to content
Back to skills

Writing Csharp

ASecurity

Check the nearest `*.csproj`, `Directory.Build.props`, `global.json`, and CI for `TargetFramework(s)`, `LangVersion`, nullable context, and analyzer policy before using newer syntax. Without an explicit `LangVersion`, the C# version follows the TFM (`net8.0` defaults to C# 12; `net6.0` defaults to C# 10, which lacks primary constructors and collection expressions). Project conventions win over these defaults, and raising `LangVersion` or the TFM to unlock syntax is a separate decision — ask f...

  • 36 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 6, 2026
ai-agentstypescriptpythongoc#shellexpresstestingapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 6 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add alexei-led/cc-thingz --skill writing-csharp --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Writing Csharp?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Writing Csharp
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/alexei-led-writing-csharp-4fddc7b1/badge)](https://www.skillsdirectory.com/skills/alexei-led-writing-csharp-4fddc7b1)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
{"description":"Idiomatic C# /.NET development. Use when writing C# code, changing `.csproj` or `.sln`, or working on ASP.NET Core apps, libraries, CLIs, workers, and xUnit/NUnit/MSTest suites. Emphasizes nullable references, async/await, boundary validation, focused `dotnet` feedback, and minimal dependencies. NOT for Go, Python, TypeScript, shell scripts, or infra-only work.","name":"writing-csharp"}
---
<!-- Pi platform guidance -->
<!-- Use installed tool names. Discover callable tools before batching independent calls in codemode; model-only UI/orchestration tools must be called directly. -->
<!-- Read required skill/instruction files through direct read when exposed or through Code Mode. If an optional pruning extension is installed, verify its output protection semantics; do not assume nested-path protection. Code Mode composes calls; subagents or controllers own durable workflows. Async subagents notify natively: yield rather than poll. -->


# C# /.NET Development

Check the nearest `*.csproj`, `Directory.Build.props`, `global.json`, and CI for `TargetFramework(s)`, `LangVersion`, nullable context, and analyzer policy before using newer syntax. Without an explicit `LangVersion`, the C# version follows the TFM (`net8.0` defaults to C# 12; `net6.0` defaults to C# 10, which lacks primary constructors and collection expressions). Project conventions win over these defaults, and raising `LangVersion` or the TFM to unlock syntax is a separate decision — ask first, don't do it on your own.

## Defaults

- BCL and existing NuGet packages first. Keep the app's existing choices: controllers vs minimal APIs, DI container, ORM, test framework.
- Nullable reference types stay on. Model absence with `?`; handle a missing result explicitly (e.g. return `NotFound`/`Problem`) instead of `!`. Never suppress a warning; fix it at the source.
- Async end to end: no `.Result`, `.Wait()`, or `GetAwaiter().GetResult()`. Pass `CancellationToken` through cancellable boundaries, including EF calls.
- Never let a singleton capture a scoped service (e.g. a `DbContext`); use `IServiceScopeFactory` or `IDbContextFactory` when a singleton needs scoped data.
- Validate request DTOs and message payloads at the handler before mapping to domain types; model binding alone is not validation. Return response DTOs from API boundaries, not entities.
- Bind and validate options at startup (`ValidateOnStart`); inject typed options instead of reading config ad hoc.
- Background services honor the stopping token; replace `Thread.Sleep` with a cancellable wait (`Task.Delay` with the token, or `PeriodicTimer`).

## CLIs

- Existing CLI stack first; the BCL is enough for small tools. Add `System.CommandLine` or Spectre.Console only when the command surface justifies it.
- Keep `Program.cs` thin: test the command handler, or a `Run(args, stdout, stderr)` seam, and assert exit code and output with `dotnet test --filter`, including a non-zero exit and a stderr message on bad input.

## References

- [testing.md](references/testing.md): read when adding or reshaping tests, or when `dotnet test` is slow.
- [linting.md](references/linting.md): read when changing `dotnet format`, analyzers, or warning policy.

Done when the relevant build/test/lint checks pass on what you changed, or you name each check that did not run and why.

Files in this skill

  • SKILL.md4 KB
  • references/cli.md1.3 KB
  • references/linting.md1.2 KB
  • references/patterns.md2.2 KB
  • references/principles.md1.9 KB
  • references/testing.md2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.