Token导航 LogoToken导航TokenDH.com
前端设计需要联网github未标认证来源可访问许可证需确认审计通过

modern-csharp-coding-standards现代 csharp 编码标准

Agent Skill

modern-csharp-coding-standards 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

4,237

周安装

182

GitHub Stars

16

下载量

1,485
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:modern-csharp-coding-standards(现代 csharp 编码标准)
来源仓库:https://github.com/wshaddix/dotnet-skills
仓库路径:skills/modern-csharp-coding-standards
安装命令:
npx skills add https://github.com/wshaddix/dotnet-skills --skill modern-csharp-coding-standards
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/wshaddix/dotnet-skills --skill modern-csharp-coding-standards

简介

modern-csharp-coding-standards 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息。

  • 适合在 Codex、Claude、Cursor、Gemini CLI 中围绕仓库状态、代码变更或协作事项进行整理。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装并使用。
  • 安装前需确认权限范围、维护状态,避免触发联网或文件读写操作。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

Modern C# Coding Standards

When to Use This Skill

Use this skill when:

  • Writing new C# code or refactoring existing code
  • Designing public APIs for libraries or services
  • Optimizing performance-critical code paths
  • Implementing domain models with strong typing
  • Building async/await-heavy applications
  • Working with binary data, buffers, or high-throughput scenarios

Core Principles

  1. Immutability by Default - Use record types and init-only properties
  2. Type Safety - Leverage nullable reference types and value objects
  3. Modern Pattern Matching - Use switch expressions and patterns extensively
  4. Async Everywhere - Prefer async APIs with proper cancellation support
  5. Zero-Allocation Patterns - Use Span<T> and Memory<T> for performance-critical code
  6. API Design - Accept abstractions, return appropriately specific types
  7. Composition Over Inheritance - Avoid abstract base classes, prefer composition
  8. Value Objects as Structs - Use readonly record struct for value objects

Naming Conventions

General Rules

ElementConventionExample
NamespacesPascalCase, dot-separatedMyCompany.MyProduct.Core
Classes, Records, StructsPascalCaseOrderService, OrderSummary
InterfacesI + PascalCaseIOrderRepository
MethodsPascalCaseGetOrderAsync
PropertiesPascalCaseOrderDate
EventsPascalCaseOrderCompleted
Public constantsPascalCaseMaxRetryCount
Private fields_camelCase_orderRepository
Parameters, localscamelCaseorderId, totalAmount
Type parametersT or T + PascalCaseT, TKey, TValue
Enum membersPascalCaseOrderStatus.Pending

Async Method Naming

Suffix async methods with Async:

public Task<Order> GetOrderAsync(int id);
public ValueTask SaveChangesAsync(CancellationToken ct);

Exception: Event handlers and interface implementations where the framework does not use the `Async` suffix (e.g., ASP.NET Core middleware `InvokeAsync` is already named by the framework).

Boolean Naming

Prefix booleans with is, has, can, should, or similar:

public bool IsActive { get; set; }
public bool HasOrders { get; }
public bool CanDelete(Order order);

Collection Naming

Use plural nouns for collections:

public IReadOnlyList<Order> Orders { get; }
public Dictionary<string, int> CountsByName { get; }

File Organization

One Type Per File

Each top-level type (class, record, struct, interface, enum) should be in its own file, named exactly as the type. Nested types stay in the containing type's file.

OrderService.cs        -> public class OrderService
IOrderRepository.cs    -> public interface IOrderRepository
OrderStatus.cs         -> public enum OrderStatus
OrderSummary.cs        -> public record OrderSummary

File-Scoped Namespaces

Always use file-scoped namespaces (C# 10+):

namespace MyApp.Services;

public class OrderService { }

Using Directives

Place using directives at the top of the file, outside the namespace. With <ImplicitUsings>enable</ImplicitUsings> (default in modern.NET), common namespaces are already imported.

Order of using directives:

  1. System.* namespaces
  2. Third-party namespaces
  3. Project namespaces

Code Style

Braces

Always use braces for control flow, even for single-line bodies:

if (order.IsValid)
{
    Process(order);
}

Expression-Bodied Members

Use expression bodies for single-expression members:

public string FullName => $"{FirstName} {LastName}";
public override string ToString() => $"Order #{Id}";

var Usage

Use var when the type is obvious from the right-hand side:

var orders = new List<Order>();
var customer = GetCustomerById(id);

IOrderRepository repo = serviceProvider.GetRequiredService<IOrderRepository>();
decimal total = CalculateTotal(items);

Null Handling

Prefer pattern matching over null checks:

if (order is not null) { }
if (order is { Status: OrderStatus.Active }) { }

var name = customer?.Name ?? "Unknown";
var orders = customer?.Orders ?? [];
items ??= [];

String Handling

Prefer string interpolation over concatenation or string.Format:

var message = $"Order {orderId} totals {total:C2}";

var json = $$"""
    {
        "id": {{orderId}},
        "name": "{{name}}"
    }
    """;

Access Modifiers

Always specify access modifiers explicitly. Do not rely on defaults:

public class OrderService
{
    private readonly IOrderRepository _repo;
    internal void ProcessBatch() { }
}

Modifier Order

access (public/private/protected/internal) -> static -> extern -> new ->
virtual/abstract/override/sealed -> readonly -> volatile -> async -> partial
public static readonly int MaxSize = 100;
protected virtual async Task<Order> LoadAsync() => await repo.GetDefaultAsync();
public sealed override string ToString() => Name;

Type Design

Seal Classes by Default

Seal classes that are not designed for inheritance. This improves performance (devirtualization) and communicates intent:

public sealed class OrderService(IOrderRepository repo)
{
}

Only leave classes unsealed when you explicitly design them as base classes.

Prefer Composition Over Inheritance

public sealed class OrderProcessor(IValidator validator, INotifier notifier)
{
    public async Task ProcessAsync(Order order)
    {
        await validator.ValidateAsync(order);
        await notifier.NotifyAsync(order);
    }
}

Interface Segregation

Keep interfaces focused. Prefer multiple small interfaces over one large one:

public interface IOrderReader
{
    Task<Order?> GetByIdAsync(int id, CancellationToken ct = default);
    Task<IReadOnlyList<Order>> GetAllAsync(CancellationToken ct = default);
}

public interface IOrderWriter
{
    Task<Order> CreateAsync(Order order, CancellationToken ct = default);
    Task UpdateAsync(Order order, CancellationToken ct = default);
}

Language Patterns

See Language Patterns for detailed guidance on:

  • Records for Immutable Data (C# 9+)
  • Value Objects as readonly record struct
  • Pattern Matching (C# 8-12)
  • Nullable Reference Types (C# 8+)
  • Composition Over Inheritance

Performance Patterns

See Performance Patterns for detailed guidance on:

  • Async/Await Best Practices
  • Span and Memory for Zero-Allocation Code

API Design Principles

See API Design Principles for detailed guidance on:

  • Accept Abstractions, Return Appropriately Specific
  • Method Signatures Best Practices

Error Handling

See Error Handling for detailed guidance on:

  • Result Type Pattern (Railway-Oriented Programming)

Testing Patterns

public record OrderBuilder
{
    public OrderId Id { get; init; } = OrderId.New();
    public CustomerId CustomerId { get; init; } = CustomerId.New();
    public Money Total { get; init; } = new Money(100m, "USD");
    public IReadOnlyList<OrderItem> Items { get; init; } = Array.Empty<OrderItem>();

    public Order Build() => new(Id, CustomerId, Total, Items);
}

[Fact]
public void CalculateDiscount_LargeOrder_AppliesCorrectDiscount()
{
    var baseOrder = new OrderBuilder().Build();
    var largeOrder = baseOrder with { Total = new Money(1500m, "USD") };

    var discount = _service.CalculateDiscount(largeOrder);

    discount.Should().Be(new Money(225m, "USD"));
}

[Theory]
[InlineData("ORD-12345", true)]
[InlineData("INVALID", false)]
public void TryParseOrderId_VariousInputs_ReturnsExpectedResult(
    string input, bool expected)
{
    var result = OrderIdParser.TryParse(input.AsSpan(), out var orderId);
    result.Should().Be(expected);
}

[Fact]
public void Money_Add_SameCurrency_ReturnsSum()
{
    var money1 = new Money(100m, "USD");
    var money2 = new Money(50m, "USD");

    var result = money1.Add(money2);

    result.Should().Be(new Money(150m, "USD"));
}

[Fact]
public void Money_Add_DifferentCurrency_ThrowsException()
{
    var usd = new Money(100m, "USD");
    var eur = new Money(50m, "EUR");

    var act = () => usd.Add(eur);
    act.Should().Throw<InvalidOperationException>()
        .WithMessage("*different currencies*");
}

CancellationToken Conventions

Accept CancellationToken as the last parameter in async methods. Use default as the default value for optional tokens:

public async Task<Order> GetOrderAsync(int id, CancellationToken ct = default)
{
    return await _repo.GetByIdAsync(id, ct);
}

Always forward the token to downstream async calls. Never ignore a received CancellationToken.


XML Documentation

Add XML docs to public API surfaces. Keep them concise:

/// <summary>
/// Retrieves an order by its unique identifier.
/// </summary>
/// <param name="id">The order identifier.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>The order, or <see langword="null"/> if not found.</returns>
public Task<Order?> GetByIdAsync(int id, CancellationToken ct = default);

Do not add XML docs to:

  • Private or internal members (unless it's a library's InternalsVisibleTo API)
  • Self-evident members (e.g., public string Name {get;})
  • Test methods

Avoid Reflection-Based Metaprogramming

See Anti-Patterns for detailed guidance on:

  • Why to avoid AutoMapper, Mapster, and similar reflection-based libraries
  • Using explicit mapping methods instead
  • UnsafeAccessorAttribute for legitimate reflection needs

Anti-Patterns to Avoid

See Anti-Patterns for detailed guidance on:

  • Mutable DTOs
  • Classes for value objects
  • Deep inheritance hierarchies
  • Exposing mutable collections
  • Forgetting CancellationToken
  • Blocking on async code

Code Organization

namespace MyApp.Domain.Orders;

public record Order(
    OrderId Id,
    CustomerId CustomerId,
    Money Total,
    OrderStatus Status,
    IReadOnlyList<OrderItem> Items
)
{
    public bool IsCompleted => Status is OrderStatus.Completed;

    public Result<Order, OrderError> AddItem(OrderItem item)
    {
        if (Status is not OrderStatus.Draft)
            return Result<Order, OrderError>.Failure(
                new OrderError("ORDER_NOT_DRAFT", "Can only add items to draft orders"));

        var newItems = Items.Append(item).ToList();
        var newTotal = new Money(
            Items.Sum(i => i.Total.Amount) + item.Total.Amount,
            Total.Currency);

        return Result<Order, OrderError>.Success(
            this with { Items = newItems, Total = newTotal });
    }
}

public enum OrderStatus
{
    Draft,
    Submitted,
    Processing,
    Completed,
    Cancelled
}

public record OrderItem(
    ProductId ProductId,
    Quantity Quantity,
    Money UnitPrice
)
{
    public Money Total => new(
        UnitPrice.Amount * Quantity.Value,
        UnitPrice.Currency);
}

public readonly record struct OrderId(Guid Value)
{
    public static OrderId New() => new(Guid.NewGuid());
}

public readonly record struct OrderError(string Code, string Message);

Analyzer Enforcement

Configure these analyzers in Directory.Build.props or .editorconfig to enforce standards automatically:

<PropertyGroup>
  <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
  <AnalysisLevel>latest-all</AnalysisLevel>
  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

Key .editorconfig rules for C# style:

[*.cs]
csharp_style_namespace_declarations = file_scoped:warning
csharp_prefer_braces = true:warning
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
dotnet_style_require_accessibility_modifiers = always:warning
csharp_style_prefer_pattern_matching = true:suggestion

Best Practices Summary

DO's

  • Use record for DTOs, messages, and domain entities
  • Use readonly record struct for value objects
  • Leverage pattern matching with switch expressions
  • Enable and respect nullable reference types
  • Use async/await for all I/O operations
  • Accept CancellationToken in all async methods
  • Use Span<T> and Memory<T> for high-performance scenarios
  • Accept abstractions (IEnumerable<T>, IReadOnlyList<T>)
  • Return appropriate interfaces or concrete types
  • Use Result<T, TError> for expected errors
  • Use ConfigureAwait(false) in library code
  • Pool buffers with ArrayPool<T> for large allocations
  • Prefer composition over inheritance
  • Avoid abstract base classes in application code

DON'Ts

  • Don't use mutable classes when records work
  • Don't use classes for value objects (use readonly record struct)
  • Don't create deep inheritance hierarchies
  • Don't ignore nullable reference type warnings
  • Don't block on async code (.Result, .Wait())
  • Don't use byte[] when Span<byte> suffices
  • Don't forget CancellationToken parameters
  • Don't return mutable collections from APIs
  • Don't throw exceptions for expected business errors
  • Don't use string concatenation in loops
  • Don't allocate large arrays repeatedly (use ArrayPool)

Knowledge Sources

Conventions in this skill are grounded in publicly available content from:

  • Microsoft Framework Design Guidelines -- The canonical reference for.NET naming, type design, and API surface conventions. Source: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/
  • C# Language Design Notes (Mads Torgersen et al.) -- Design rationale behind C# language features that affect coding standards. Key decisions relevant to this skill: file-scoped namespaces (reducing nesting for readability), pattern matching over type checks (expressiveness), required members (compile-time initialization safety), and var usage guidelines (readability-first). Source: https://github.com/dotnet/csharplang/tree/main/meetings

Additional Resources

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

39%
按下载量换算579

Claude

30.34%
按下载量换算451

Cursor

18.61%
按下载量换算276

Gemini CLI

9.45%
按下载量换算140

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills