csharp-codegen
Skill0 starsChanged 3 months agoApache-2.0View on GitHub
Generate and review C# code following .NET naming conventions, Microsoft Framework Design Guidelines, and general software principles (KISS, YAGNI, SOLID). Use this skill whenever the user asks to write, create, implement, generate, refactor, or review C# code — including classes, interfaces, services, CLI tools, ASP.NET Core Web API controllers, Entity Framework Core DbContext/entities/repositories, unit tests, or any .NET component. Also trigger when the user asks to review C# for guideline compliance, audit existing code for anti-patterns, or produce idiomatic .NET implementations. This skill ensures all generated code is immediately formatted with `dotnet format` compatible style and is production-ready.
In this repository4 other files it gives its agents.
- adr-writerSkill
- react-code-reviewSkill
- spring-boot-api-reviewerSkill
- translateSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
21 rules. About 0 are common, 10 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈10
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 26
Always follow these rules — they are non-negotiable:
- Distinctive: line 43
No Hungarian notation, no underscores in non-field names
- Very specific: line 44
No abbreviations unless universally accepted (e.g., Id, Url, Http)
- Very specific: line 45
No language-specific type names in public APIs (use GetLength, not GetInt)
- Very specific: line 54
All generated code must be compatible with dotnet format out of the box.
- Very specific: line 64
Use ? for nullable reference types and value types where needed
- Very specific: line 65
Use ArgumentNullException.ThrowIfNull() for null guards in public APIs
- Distinctive: line 68
Use modern language features when they improve clarity:
- Very specific: line 84
Do NOT have a property and a method with the same name (e.g., TextWriter property and GetTextWriter method is wrong)
- Distinctive: line 88
Use exceptions for execution failures, not control flow
- Distinctive: line 89
Do NOT return error codes.
- Very specific: line 90
Do NOT throw NullReferenceException, IndexOutOfRangeException, AccessViolationException from public APIs
- Very specific: line 91
Use Try-Parse Pattern for performance-sensitive parsing: bool TryParse(string input, out T result)
- Distinctive: line 92
Use Tester-Doer Pattern when checking preconditions avoids expensive throws
- Very specific: line 93
Document all exceptions thrown by public members with <exception> XML doc tags
- Very specific: line 97
Avoid out or ref parameters in public APIs (prefer return values or records)
- Very specific: line 98
Use CancellationToken as the last parameter in async methods (optional, with default)
- Distinctive: line 117
Check whether tests are needed (always offer to generate tests)
- Distinctive: line 155
Always present code as complete, compilable files.
- Distinctive: line 166
Read all provided files before commenting
- Distinctive: line 172
Check every file for:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
C# Code Generation & Review Skill
Generate and review idiomatic, production-ready C# code that strictly follows Microsoft's .NET naming conventions, Framework Design Guidelines, and general software engineering principles.
Core Principles
Code Quality
- KISS – Prefer the simplest solution that correctly solves the problem
- YAGNI – Do not add abstractions or features not requested
- SOLID – Apply where it adds genuine value; avoid over-engineering
- DRY – Eliminate duplication, but don't abstract prematurely
- Readability first – Code is read far more than it's written
Balance
Maintainability and performance must be balanced. Optimize only when there is a measurable need. Premature optimization is the root of unnecessary complexity.
Naming Conventions
Always follow these rules — they are non-negotiable:
| Element | Convention | Example |
| Class, Struct, Record | PascalCase | WorktreeManager |
| Interface | I prefix + PascalCase | IWorktreeRepository |
| Enum | PascalCase (singular for non-flags, plural for flags) | BranchStatus, FilePermissions |
| Method | PascalCase, verb or verb phrase | CreateWorktree, TryParseArgs |
| Property | PascalCase, noun or adjective | BranchName, IsReadOnly |
| Event | PascalCase, verb phrase | WorktreeCreated |
| Local variable, parameter | camelCase | branchName, outputPath |
| Private instance field | _ prefix + camelCase | _fileSystem |
| Private static field | s_ prefix + camelCase | s_defaultPath |
| Constant | PascalCase | MaxRetryCount |
| Generic type parameter | T prefix (if descriptive), or T alone | TResult, T |
Rules:
- No Hungarian notation, no underscores in non-field names
- No abbreviations unless universally accepted (e.g.,
Id,Url,Http) - No language-specific type names in public APIs (use
GetLength, notGetInt) - Attribute types must end with
Attribute - Async methods must end with
Async
Code Structure Rules
Formatting (dotnet format compliant)
All generated code must be compatible with dotnet format out of the box. Do NOT deviate from these:
- 4-space indentation (no tabs)
- Opening braces
{on the same line for expressions; new line for type and method declarations - One blank line between methods
usingdirectives at the top, outside namespace- File-scoped namespaces (
namespace Foo;) for single-type files varfor obvious types; explicit types when the type is not immediately clear
Nullability
- Enable nullable reference types (
<Nullable>enable</Nullable>) - Use
?for nullable reference types and value types where needed - Use
ArgumentNullException.ThrowIfNull()for null guards in public APIs
Modern C# Features
Use modern language features when they improve clarity:
- Records for immutable data transfer objects
- Pattern matching over type-checking casts
is not null/is nullover!= null/== nullswitchexpressions over verbose switch statements- Primary constructors for simple DI scenarios
Span<T>/Memory<T>for performance-sensitive buffer operations (only when justified)
API Design Guidelines (from Microsoft Framework Design Guidelines)
Members
- Methods must be verbs or verb phrases:
CreateWorktree,ParseBranchName - Properties must be nouns or adjectives:
BranchName,IsValid - Boolean properties use affirmative phrasing:
CanSeek,IsEnabled,HasValue - Do NOT have a property and a method with the same name (e.g.,
TextWriterproperty andGetTextWritermethod is wrong) - Collection properties use plural names describing items:
Worktrees, notWorktreeList
Exceptions
- Use exceptions for execution failures, not control flow
- Do NOT return error codes; throw exceptions
- Do NOT throw
NullReferenceException,IndexOutOfRangeException,AccessViolationExceptionfrom public APIs - Use Try-Parse Pattern for performance-sensitive parsing:
bool TryParse(string input, out T result) - Use Tester-Doer Pattern when checking preconditions avoids expensive throws
- Document all exceptions thrown by public members with
<exception>XML doc tags - See
references/exceptions.mdfor detailed guidance
Parameters
- Avoid
outorrefparameters in public APIs (prefer return values or records) - Use
CancellationTokenas the last parameter in async methods (optional, with default) - Validate all public API arguments and throw
ArgumentException,ArgumentNullException, orArgumentOutOfRangeException
Workflow Selection
Choose the appropriate workflow based on the request:
- Generating new code → follow Code Generation Workflow
- Reviewing existing code → follow Code Review Workflow
Code Generation Workflow
Step 1: Understand the request
Before writing code:
- Identify what type of component is needed (class, interface, CLI command, service, controller, entity, repository, test, etc.)
- Identify dependencies and the target framework (check
.csprojif provided) - Check whether tests are needed (always offer to generate tests)
Step 2: Select the right references
Load reference files based on the component type:
- General naming and structure → this file is sufficient
- Exceptions and error handling →
references/exceptions.md - Async and Task-based patterns →
references/async.md - Unit testing (xUnit + Moq + Shouldly) →
references/testing.md - System.CommandLine CLI commands →
references/cli.md - System.IO.Abstractions (file system abstraction) →
references/filesystem.md - ASP.NET Core Web API (controllers, routing, DI, error handling) →
references/aspnetcore.md - Entity Framework Core (DbContext, entities, queries, migrations) →
references/efcore.md
Step 3: Write the code
Follow the checklist:
Before writing:
- Plan the public API surface before writing implementation
- Identify which interfaces the type should implement
- Identify which exceptions should be thrown
While writing:
- All public members have XML documentation (
///) - Nullable reference types enabled and correct
- All public arguments validated
- Async methods suffixed with
Asyncand acceptCancellationToken - No logic in constructors beyond assignment
- Static methods for stateless utilities
privateas the default access modifier; widen only when needed
After writing:
- Verify format matches
dotnet formatoutput (4-space indent, correct brace placement) - Confirm no abbreviations in public API names
- Confirm no Hungarian notation
- Confirm no error codes returned
Step 4: Output format
Always present code as complete, compilable files. Include:
- The complete file with
usingdirectives and namespace - A brief explanation of design decisions
- Example usage (inline comment or separate snippet)
- Offer to generate unit tests if not already requested
Code Review Workflow
Step 1: Understand scope
- Read all provided files before commenting
- Identify which stack is in use: CLI / ASP.NET Core / EF Core / plain class library
- Load the relevant reference files for that stack (same list as above)
Step 2: Review against all applicable rules
Check every file for:
Naming & formatting
- All naming conventions followed (see table above)
- No Hungarian notation, no abbreviations in public names
- No tabs; 4-space indent; file-scoped namespaces used
- Async methods suffixed with
Async
API design
- Methods are verbs; properties are nouns/adjectives
- No error codes returned — exceptions used instead
- No
NullReferenceException/IndexOutOfRangeExceptionfrom public APIs CancellationTokenaccepted where appropriate
Nullability & safety
- Nullable reference types enabled and correctly annotated
- All public API arguments validated before use
Stack-specific (load relevant reference and apply its checklist)
- ASP.NET Core: controller shape, routing, DI lifetimes, response types, error handling
- EF Core: no N+1, AsNoTracking on reads, async EF methods, no raw SQL injection
Tests
- Tests exist for public behaviour
- AAA structure followed; Shouldly used; no raw
Assert.
Step 3: Report findings
Structure feedback by severity:
🔴 CRITICAL — Must fix: bugs, security issues, data corruption risk, lifetime mismatches
🟠 HIGH — Should fix before merge: naming violations, missing argument validation, anti-patterns
🟡 MEDIUM — Improvements: test coverage gaps, missing XML docs, suboptimal queries
🟢 LOW — Optional polish: style, refactoring opportunities
✅ POSITIVE — What is done well (always include at least one)
For each issue provide:
- The problematic code snippet
- Why it is a problem
- A corrected example
- Reference to the specific guideline broken
Examples
✅ Correct: Service class with DI, nullability, and documentation
using System.IO.Abstractions;
namespace Kuju63.WorkTree;
/// <summary>
/// Manages git worktree lifecycle operations.
/// </summary>
public sealed class WorktreeManager(IFileSystem fileSystem, IGitRunner gitRunner)
{
private readonly IFileSystem _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
private readonly IGitRunner _gitRunner = gitRunner ?? throw new ArgumentNullException(nameof(gitRunner));
/// <summary>
/// Creates a new worktree at the specified path for the given branch.
/// </summary>
/// <param name="path">The directory path for the new worktree.</param>
/// <param name="branchName">The branch name to check out in the worktree.</param>
/// <param name="cancellationToken">A token to observe for cancellation requests.</param>
/// <exception cref="ArgumentNullException">
/// Thrown when <paramref name="path"/> or <paramref name="branchName"/> is null.
/// </exception>
/// <exception cref="WorktreeException">Thrown when git fails to create the worktree.</exception>
public async Task CreateAsync(string path, string branchName, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(path);
ArgumentNullException.ThrowIfNull(branchName);
await _gitRunner.RunAsync(["worktree", "add", path, branchName], cancellationToken);
}
}✅ Correct: Record for data transfer
namespace Kuju63.WorkTree;
/// <summary>
/// Represents an existing git worktree entry.
/// </summary>
public record WorktreeInfo(string Path, string BranchName, bool IsLocked);✅ Correct: Try-Parse pattern
/// <summary>Parses a branch name from raw git output.</summary>
public static bool TryParseBranchName(string input, out string branchName)
{
branchName = string.Empty;
if (string.IsNullOrWhiteSpace(input))
return false;
var trimmed = input.Trim();
if (!trimmed.StartsWith("refs/heads/", StringComparison.Ordinal))
return false;
branchName = trimmed["refs/heads/".Length..];
return true;
}❌ Wrong: Naming and style violations
// BAD: Hungarian notation, abbreviation, missing nullable, no docs
class wtMgr {
private IFileSystem fs; // 'fs' abbreviation, missing _prefix, no ?
public string getBranchNm() => ""; // lowercase method, abbreviation
}Quick Reference
| Situation | What to do |
| Need to return multiple values | Use a record or ValueTuple |
| Method might fail for known reasons | Use Try-Parse pattern |
| Checking precondition is cheap | Use Tester-Doer pattern |
| Need file system operations | Use IFileSystem from System.IO.Abstractions |
| Async operation | Add Async suffix, accept CancellationToken last |
| Parsing CLI args | Use System.CommandLine — see references/cli.md |
| Writing tests | Use xUnit + Moq + Shouldly — see references/testing.md |
| Building Web API endpoint | Use [ApiController] + ControllerBase — see references/aspnetcore.md |
| Database access with EF Core | Use scoped DbContext, async methods, AsNoTracking for reads — see references/efcore.md |
| Reviewing code | Follow Code Review Workflow; load stack-specific references |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

