Agent skill

Dotnet Patterns

by affaan-m in affaan-m/ECC

惯用的C和.NET模式、约定、依赖注入、async/await以及构建健壮、可维护的.NET应用程序的最佳实践. An agent skill from affaan-m/ECC.

MITAuto-check passedDevelopment

Install Dotnet Patterns

skills CLI
$ npx skills add affaan-m/ECC --skill dotnet-patterns -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install affaan-m/ECC dotnet-patterns --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .claude/skills && cp -r skills-src/docs/zh-CN/skills/dotnet-patterns .claude/skills/dotnet-patterns && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
dotnet-patterns
GitHub stars
275k
Token cost
~2.1k tokens
SKILL.md length
83 words
Files
1
Skills in repo
645
Repo updated
First seen
Licence
MIT

At a glance

惯用的C和.NET模式、约定、依赖注入、async/await以及构建健壮、可维护的.NET应用程序的最佳实践. An agent skill from affaan-m/ECC.

  • Works in 3 steps: 优先使用不可变性 → 显式优于隐式 → 依赖抽象
  • Tasks that involve Async programming
  • SKILL.md covers 何时激活, 核心原则, 异步/等待模式 and 选项模式, plus 6 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Dotnet Patterns is an agent skill from affaan-m/ECC. 惯用的C和.NET模式、约定、依赖注入、async/await以及构建健壮、可维护的.NET应用程序的最佳实践。

Its SKILL.md is about 2.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering Async programming. It works with .NET and C#. The repository describes itself as: The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond. The licence is MIT.

When your agent uses it

  • Tasks that involve Async programming

Example prompts

  • “/dotnet-patterns”

Workflow steps

3 steps, taken from the step headings in SKILL.md.

  1. 优先使用不可变性
  2. 显式优于隐式
  3. 依赖抽象

What it can do on your machine

Read from SKILL.md and the folder at commit ef648e0. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are csharp).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Dotnet Patterns loads about 2.1k tokens when it runs. Until then it costs about 18 tokens; SKILL.md has 83 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~18
When it runs · the whole SKILL.md, loaded when a task matches
~2.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from affaan-m/ECC at commit ef648e0, republished under its MIT licence (© affaan-m). 83 words, ~2,089 tokens.

Download SKILL.mdSave it as .claude/skills/dotnet-patterns/SKILL.md (or your agent's skills folder).
name
dotnet-patterns
description
惯用的C#和.NET模式、约定、依赖注入、async/await以及构建健壮、可维护的.NET应用程序的最佳实践。
origin
ECC

.NET 开发模式

用于构建健壮、高性能且可维护应用程序的惯用 C# 和 .NET 模式。

何时激活

  • 编写新的 C# 代码时
  • 审查 C# 代码时
  • 重构现有 .NET 应用程序时
  • 使用 ASP.NET Core 设计服务架构时

核心原则

1. 优先使用不可变性

对数据模型使用记录和仅初始化属性。可变性应作为明确且有理由的选择。

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. 显式优于隐式

明确表达可空性、访问修饰符和意图。

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. 依赖抽象

对服务边界使用接口。通过依赖注入容器注册。

csharp
// Good: Interface-based dependency
public interface IOrderRepository
{
    Task<Order?> FindByIdAsync(Guid id, CancellationToken cancellationToken);
    Task<IReadOnlyList<Order>> FindByCustomerAsync(string customerId, CancellationToken cancellationToken);
    Task AddAsync(Order order, CancellationToken cancellationToken);
}

// Registration
builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();

异步/等待模式

正确使用异步
csharp
// Good: Async all the way, with CancellationToken
public async Task<OrderSummary> GetOrderSummaryAsync(
    Guid orderId,
    CancellationToken cancellationToken)
{
    var order = await _repository.FindByIdAsync(orderId, cancellationToken)
        ?? throw new NotFoundException($"Order {orderId} not found");

    var customer = await _customerService.GetAsync(order.CustomerId, cancellationToken);

    return new OrderSummary(order, customer);
}

// Bad: Blocking on async
public OrderSummary GetOrderSummary(Guid orderId)
{
    var order = _repository.FindByIdAsync(orderId, CancellationToken.None).Result; // Deadlock risk
    return new OrderSummary(order);
}
并行异步操作
csharp
// Good: Concurrent independent operations
public async Task<DashboardData> LoadDashboardAsync(CancellationToken cancellationToken)
{
    var ordersTask = _orderService.GetRecentAsync(cancellationToken);
    var metricsTask = _metricsService.GetCurrentAsync(cancellationToken);
    var alertsTask = _alertService.GetActiveAsync(cancellationToken);

    await Task.WhenAll(ordersTask, metricsTask, alertsTask);

    return new DashboardData(
        Orders: await ordersTask,
        Metrics: await metricsTask,
        Alerts: await alertsTask);
}

选项模式

将配置节绑定到强类型对象。

csharp
public sealed class SmtpOptions
{
    public const string SectionName = "Smtp";

    public required string Host { get; init; }
    public required int Port { get; init; }
    public required string Username { get; init; }
    public bool UseSsl { get; init; } = true;
}

// Registration
builder.Services.Configure<SmtpOptions>(
    builder.Configuration.GetSection(SmtpOptions.SectionName));

// Usage via injection
public class EmailService(IOptions<SmtpOptions> options)
{
    private readonly SmtpOptions _smtp = options.Value;
}

结果模式

对预期失败返回显式成功/失败,而非抛出异常。

csharp
public sealed record Result<T>
{
    public bool IsSuccess { get; }
    public T? Value { get; }
    public string? Error { get; }

    private Result(T value) { IsSuccess = true; Value = value; }
    private Result(string error) { IsSuccess = false; Error = error; }

    public static Result<T> Success(T value) => new(value);
    public static Result<T> Failure(string error) => new(error);
}

// Usage
public async Task<Result<Order>> PlaceOrderAsync(CreateOrderRequest request)
{
    if (request.Items.Count == 0)
        return Result<Order>.Failure("Order must contain at least one item");

    var order = Order.Create(request);
    await _repository.AddAsync(order, CancellationToken.None);
    return Result<Order>.Success(order);
}

使用 EF Core 的仓储模式

csharp
public sealed class SqlOrderRepository : IOrderRepository
{
    private readonly AppDbContext _db;

    public SqlOrderRepository(AppDbContext db) => _db = db;

    public async Task<Order?> FindByIdAsync(Guid id, CancellationToken cancellationToken)
    {
        return await _db.Orders
            .Include(o => o.Items)
            .AsNoTracking()
            .FirstOrDefaultAsync(o => o.Id == id, cancellationToken);
    }

    public async Task<IReadOnlyList<Order>> FindByCustomerAsync(
        string customerId,
        CancellationToken cancellationToken)
    {
        return await _db.Orders
            .Where(o => o.CustomerId == customerId)
            .OrderByDescending(o => o.CreatedAt)
            .AsNoTracking()
            .ToListAsync(cancellationToken);
    }

    public async Task AddAsync(Order order, CancellationToken cancellationToken)
    {
        _db.Orders.Add(order);
        await _db.SaveChangesAsync(cancellationToken);
    }
}

中间件与管道

csharp
// Custom middleware
public sealed class RequestTimingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestTimingMiddleware> _logger;

    public RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var stopwatch = Stopwatch.StartNew();
        try
        {
            await _next(context);
        }
        finally
        {
            stopwatch.Stop();
            _logger.LogInformation(
                "Request {Method} {Path} completed in {ElapsedMs}ms with status {StatusCode}",
                context.Request.Method,
                context.Request.Path,
                stopwatch.ElapsedMilliseconds,
                context.Response.StatusCode);
        }
    }
}

最小 API 模式

csharp
// Organized with route groups
var orders = app.MapGroup("/api/orders")
    .RequireAuthorization()
    .WithTags("Orders");

orders.MapGet("/{id:guid}", async (
    Guid id,
    IOrderRepository repository,
    CancellationToken cancellationToken) =>
{
    var order = await repository.FindByIdAsync(id, cancellationToken);
    return order is not null
        ? TypedResults.Ok(order)
        : TypedResults.NotFound();
});

orders.MapPost("/", async (
    CreateOrderRequest request,
    IOrderService service,
    CancellationToken cancellationToken) =>
{
    var result = await service.PlaceOrderAsync(request, cancellationToken);
    return result.IsSuccess
        ? TypedResults.Created($"/api/orders/{result.Value!.Id}", result.Value)
        : TypedResults.BadRequest(result.Error);
});

守卫子句

csharp
// Good: Early returns with clear validation
public async Task<ProcessResult> ProcessPaymentAsync(
    PaymentRequest request,
    CancellationToken cancellationToken)
{
    ArgumentNullException.ThrowIfNull(request);

    if (request.Amount <= 0)
        throw new ArgumentOutOfRangeException(nameof(request.Amount), "Amount must be positive");

    if (string.IsNullOrWhiteSpace(request.Currency))
        throw new ArgumentException("Currency is required", nameof(request.Currency));

    // Happy path continues here without nesting
    var gateway = _gatewayFactory.Create(request.Currency);
    return await gateway.ChargeAsync(request, cancellationToken);
}

应避免的反模式

反模式修复方案
async void 方法返回 Task(事件处理程序除外)
.Result 或 .Wait()使用 await
catch (Exception) { }处理或带上下文重新抛出
构造函数中的 new Service()使用构造函数注入
public 字段使用带适当访问器的属性
业务逻辑中的 dynamic使用泛型或显式类型
可变的 static 状态使用依赖注入作用域或 ConcurrentDictionary
循环中的 string.Format使用 StringBuilder 或内插字符串处理程序

© affaan-m, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in docs/zh-CN/skills/dotnet-patterns of affaan-m/ECC.

Open the folder on GitHubat commit ef648e0

Compare with similar skills

Dotnet Patterns next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Dotnet Patterns compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Dotnet Patterns this skillaffaan-m/ECC275k—~2.1kAutomated safety check: PassMIT
Akka.NET Best PracticesAaronontheweb/dotnet-skills1.2k1 repos~3.3kAutomated safety check: PassMIT
Dotnet Csharpnovotnyllc/dotnet-artisan233—~1.7kAutomated safety check: PassMIT
Csharp Concurrency PatternsAaronontheweb/dotnet-skills1.2k1 repos~2.2kAutomated safety check: PassMIT
Csharp Prodavila7/claude-code-templates32k8 repos~538Automated safety check: PassMIT
Csharp Patternssoftspark/ai-toolkit179—~3.6kAutomated safety check: PassApache-2.0

Similar skills

  • Akka.NET Best Practices

    Aaronontheweb/dotnet-skills

    Guidance for Akka.NET actor systems covering EventStream versus DistributedPubSub, supervision, Props versus DependencyResolver, work distribution and testable cluster code.

    1.2k GitHub starsUsed in 1 repo~3.3k tokens
    DevelopmentAuto-check passed
  • Dotnet Csharp

    novotnyllc/dotnet-artisan

    Baseline C skill loaded for every .NET code path. An agent skill from novotnyllc/dotnet-artisan.

    233 GitHub stars~1.7k tokensUpdated today
    DevelopmentAuto-check passed
  • Csharp Concurrency Patterns

    Aaronontheweb/dotnet-skills

    Choosing the right concurrency abstraction in .NET - from async/await for I/O to Channels for producer/consumer to Akka.NET for stateful entity management.

    1.2k GitHub starsUsed in 1 repo~2.2k tokens
    DevelopmentAuto-check passed
  • Csharp Pro

    davila7/claude-code-templates

    Write modern C code with advanced features like records, pattern matching, and async/await.

    32k GitHub starsUsed in 8 repos~538 tokens
    DevelopmentAuto-check passed
  • Csharp Patterns

    softspark/ai-toolkit

    C/.NET: LINQ, async/await, DI, records, nullable refs, ASP.NET Core, EF Core, MediatR.

    179 GitHub stars~3.6k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Csharp Idioms

    irahardianto/awesome-agv

    Modern C (10+/.NET) coding idioms: nullable reference types, records, pattern matching, async/await with CancellationTokens, LINQ performance, and DI.

    157 GitHub stars~1.3k tokensUpdated 3 days ago
    DevelopmentAuto-check passed

More from affaan-m/ECC

All 645 skills in this repo
  • Videodb

    affaan-m/ECC

    Ingest, index, search, edit, and monitor video and audio with the VideoDB Python SDK — upload from files, URLs, or RTSP feeds, build spoken and scene indexes with timestamped search and playable…

    275k GitHub starsUsed in 3 repos~3.5k tokens
    Auto-check: notes
  • Rules Distillation

    affaan-m/ECC

    Scans installed skills for principles that recur across them and proposes rule-file changes: append, revise, add a section, create a file or leave as covered.

    275k GitHub starsUsed in 2 repos~2.3k tokens
    Auto-check passed
  • Builds DRAFT counterparty agreements from one markdown template and a small JSON spec per party, with clauses picked by the party's role.

    275k GitHub stars~2.9k tokensUpdated 3 days ago
    Auto-check passed
  • Measures whether agents actually follow a skill, rule or agent definition by generating scenarios at three strictness levels and scoring tool-call traces.

    275k GitHub starsUsed in 1 repo~623 tokens
    Auto-check passed
  • Instinct-based learning system that observes sessions via hooks, creates atomic instincts with confidence scoring, and evolves them into skills/commands/agents.

    275k GitHub stars~3.5k tokensUpdated 3 days ago
    Auto-check passed
  • Adds one optional external Codex critique that tries to break a council's decision draft, sent to OpenAI only after you consent.

    275k GitHub stars~1.5k tokensUpdated 3 days ago
    Auto-check passed

Works with

Categories

Questions about Dotnet Patterns

What does Dotnet Patterns do?

惯用的C和.NET模式、约定、依赖注入、async/await以及构建健壮、可维护的.NET应用程序的最佳实践. An agent skill from affaan-m/ECC. Dotnet Patterns is an agent skill from affaan-m/ECC.

When should I use Dotnet Patterns?

Dotnet Patterns fits situations like: tasks that involve Async programming.

How do I install Dotnet Patterns in Claude Code?

Run `npx skills add affaan-m/ECC --skill dotnet-patterns -a claude-code`. Or copy the skill folder (docs/zh-CN/skills/dotnet-patterns in affaan-m/ECC) into .claude/skills/dotnet-patterns in your project. Claude Code loads it when a task matches its description.

How do I install Dotnet Patterns in Codex?

Run `npx skills add affaan-m/ECC --skill dotnet-patterns -a codex`. Or copy the skill folder (docs/zh-CN/skills/dotnet-patterns in affaan-m/ECC) into .agents/skills/dotnet-patterns in your project. Codex loads it when a task matches its description.

Can I use Dotnet Patterns in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add affaan-m/ECC --skill dotnet-patterns -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/dotnet-patterns, .gemini/skills/dotnet-patterns, .github/skills/dotnet-patterns and .opencode/skills/dotnet-patterns in your project.

What does Dotnet Patterns need to run?

SKILL.md names no scripts, command-line tools or credentials: Dotnet Patterns is instructions for the agent only.

Does Dotnet Patterns access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Dotnet Patterns safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Dotnet Patterns use?

Dotnet Patterns is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Dotnet Patterns use?

About 2.1k tokens (SKILL.md is roughly 8.4k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Dotnet Patterns?

Skills that share tags, products or a category with Dotnet Patterns: Akka.NET Best Practices (Aaronontheweb/dotnet-skills, 1.2k stars), Dotnet Csharp (novotnyllc/dotnet-artisan, 233 stars), Csharp Concurrency Patterns (Aaronontheweb/dotnet-skills, 1.2k stars) and Csharp Pro (davila7/claude-code-templates, 32k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Dotnet Patterns?

affaan-m (a GitHub user) maintains it in affaan-m/ECC, which has 275,023 GitHub stars. The repository holds 645 skills in this directory. The repository was last updated on October 5, 2026.

Source: affaan-m/ECC on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.