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

dotnet-csharp-modern-patternsdotnet csharp 现代模式

Agent Skill

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

总安装

559

周安装

24

GitHub Stars

15

下载量

196
CodexClaudeCursorGemini CLI

安装说明

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

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

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

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

命令行安装

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

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

简介

该技能提供现代 C# 语言特性的适配指导,根据项目目标框架选择合适语法。

  • 适用于需要利用最新语言功能的 ASP.NET Core、API 或 Worker 服务开发。
  • 核心能力包括 TFM 到 C# 版本的映射、新特性使用说明和模式匹配优化。
  • 使用时应先运行版本检测技能确定项目配置,再结合编码标准使用。
  • 安装前需确认项目支持 .NET 8+ 并正确配置目标框架。

SKILL.md

dotnet-csharp-modern-patterns

Modern C# language feature guidance adapted to the project's target framework. Always run [skill:dotnet-version-detection] first to determine TFM and C# version.

Cross-references: [skill:dotnet-csharp-coding-standards] for naming/style conventions, [skill:dotnet-csharp-async-patterns] for async-specific patterns.


Quick Reference: TFM to C# Version

TFMC#Key Language Features
net8.012Primary constructors, collection expressions, alias any type
net9.013params collections, Lock type, partial properties
net10.014field keyword, extension blocks, nameof unbound generics
net11.015 (preview)Collection expression with() arguments

Records

Use records for immutable data transfer objects, value semantics, and domain modeling where equality is based on values rather than identity.

Record Classes (reference type)

// Positional record: concise, immutable, value equality
public record OrderSummary(int OrderId, decimal Total, DateOnly OrderDate);

// With additional members
public record Customer(string Name, string Email)
{
    public string DisplayName => $"{Name} <{Email}>";
}

Record Structs (value type, C# 10+)

// Positional record struct: value type with value semantics
public readonly record struct Point(double X, double Y);

// Mutable record struct (rare -- prefer readonly)
public record struct MutablePoint(double X, double Y);

When to Use Records vs Classes

Use CasePrefer
DTOs, API responsesrecord
Domain value objects (Money, Email)readonly record struct
Entities with identity (User, Order)class
High-throughput, small datareadonly record struct
Inheritance neededrecord (class-based)

Non-destructive Mutation

var updated = order with { Total = order.Total + tax };

Primary Constructors (C# 12+, net8.0+)

Capture constructor parameters directly in the class/struct body. Parameters become available throughout the type but are not fields or properties -- they are captured state.

For Services (DI injection)

public class OrderService(IOrderRepository repo, ILogger<OrderService> logger)
{
    public async Task<Order> GetAsync(int id)
    {
        logger.LogInformation("Fetching order {OrderId}", id);
        return await repo.GetByIdAsync(id);
    }
}

Gotchas

  • Primary constructor parameters are mutable captures, not readonly fields. If immutability matters, assign to a readonly field in the body.
  • Do not use primary constructors when you need to validate parameters at construction time -- use a traditional constructor with guard clauses instead.
  • For records, positional parameters become public properties automatically. For classes/structs, they remain private captures.
// Explicit readonly field when immutability matters
public class Config(string connectionString)
{
    private readonly string _connectionString = connectionString
        ?? throw new ArgumentNullException(nameof(connectionString));
}

Collection Expressions (C# 12+, net8.0+)

Unified syntax for creating collections with [...].

// Array
int[] numbers = [1, 2, 3];

// List
List<string> names = ["Alice", "Bob"];

// Span
ReadOnlySpan<byte> bytes = [0x00, 0xFF];

// Spread operator
int[] combined = [..first, ..second, 99];

// Empty collection
List<int> empty = [];

Collection Expression with Arguments (C# 15 preview, net11.0+)

Specify capacity, comparers, or other constructor arguments:

// Capacity hint
List<int> nums = [with(capacity: 1000), ..Generate()];

// Custom comparer
HashSet<string> set = [with(comparer: StringComparer.OrdinalIgnoreCase), "Alice", "bob"];

// Dictionary with comparer
Dictionary<string, int> map = [with(comparer: StringComparer.OrdinalIgnoreCase),
    new("key1", 1), new("key2", 2)];
net11.0+ only. Requires <LangVersion>preview</LangVersion>. Do not use on earlier TFMs.

Pattern Matching

Switch Expressions (C# 8+)

string GetDiscount(Customer customer) => customer switch
{
    { Tier: "Gold", YearsActive: > 5 } => "30%",
    { Tier: "Gold" } => "20%",
    { Tier: "Silver" } => "10%",
    _ => "0%"
};

List Patterns (C# 11+)

bool IsValid(int[] data) => data is [> 0, .., > 0]; // first and last positive

string Describe(int[] values) => values switch
{
    [] => "empty",
    [var single] => $"single: {single}",
    [var first, .., var last] => $"range: {first}..{last}"
};

Type and Property Patterns

decimal CalculateShipping(object package) => package switch
{
    Letter { Weight: < 50 } => 0.50m,
    Parcel { Weight: var w } when w < 1000 => 5.00m + w * 0.01m,
    Parcel { IsOversized: true } => 25.00m,
    _ => 10.00m
};

required Members (C# 11+)

Force callers to initialize properties at construction via object initializers.

public class UserDto
{
    public required string Name { get; init; }
    public required string Email { get; init; }
    public string? Phone { get; init; }
}

// Compiler enforces Name and Email
var user = new UserDto { Name = "Alice", Email = "alice@example.com" };

Useful for DTOs that need to be deserialized (System.Text.Json honors required in.NET 8+).


field Keyword (C# 14, net10.0+)

Access the compiler-generated backing field directly in property accessors.

public class TemperatureSensor
{
    public double Reading
    {
        get => field;
        set => field = value >= -273.15
            ? value
            : throw new ArgumentOutOfRangeException(nameof(value));
    }
}

Replaces the manual pattern of declaring a private field plus a property with custom logic. Use when you need validation or transformation in a setter without a separate backing field.

net10.0+ only. On earlier TFMs, use a traditional private field.

Extension Blocks (C# 14, net10.0+)

Group extension members for a type in a single block.

public static class EnumerableExtensions
{
    extension<T>(IEnumerable<T> source) where T : class
    {
        public IEnumerable<T> WhereNotNull()
            => source.Where(x => x is not null);

        public bool IsEmpty()
            => !source.Any();
    }
}
net10.0+ only. On earlier TFMs, use traditional static extension methods.

Alias Any Type (using, C# 12+, net8.0+)

using Point = (double X, double Y);
using UserId = System.Guid;

Point origin = (0, 0);
UserId id = UserId.NewGuid();

Useful for tuple aliases and domain type aliases without creating a full type.


params Collections (C# 13, net9.0+)

params now supports additional collection types beyond arrays, including Span<T>, ReadOnlySpan<T>, and types implementing certain collection interfaces.

public void Log(params ReadOnlySpan<string> messages)
{
    foreach (var msg in messages)
        Console.WriteLine(msg);
}

// Callers: compiler may avoid heap allocation with span-based params
Log("hello", "world");
net9.0+ only. On net8.0, params only supports arrays.

Lock Type (C# 13, net9.0+)

Use System.Threading.Lock instead of object for locking.

private readonly Lock _lock = new();

public void DoWork()
{
    lock (_lock)
    {
        // thread-safe operation
    }
}

Lock provides a Scope-based API for advanced scenarios and is more expressive than lock (object).

net9.0+ only. On net8.0, use private readonly object _gate = new(); and lock (_gate).

Partial Properties (C# 13, net9.0+)

Partial properties enable source generators to define property signatures that users implement, or vice versa.

// In generated file
public partial class ViewModel
{
    public partial string Name { get; set; }
}

// In user file
public partial class ViewModel
{
    private string _name = "";
    public partial string Name
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }
}
net9.0+ only. See [skill:dotnet-csharp-source-generators] for generator patterns.

nameof for Unbound Generic Types (C# 14, net10.0+)

string name = nameof(List<>);      // "List"
string name2 = nameof(Dictionary<,>); // "Dictionary"

Useful in logging, diagnostics, and reflection scenarios.

net10.0+ only.

Polyfill Guidance for Multi-Targeting

When targeting multiple TFMs, newer language features may not compile on older targets. Use these approaches:

  1. PolySharp -- Polyfills compiler-required types (IsExternalInit, RequiredMemberAttribute, etc.) so language features like init, required, and record work on older TFMs.
  2. Polyfill -- Polyfills runtime APIs (e.g., string.Contains(char) for netstandard2.0).
  3. Conditional compilation -- Use #if for features that cannot be polyfilled:
#if NET10_0_OR_GREATER
    // Use field keyword
    public double Value { get => field; set => field = Math.Max(0, value); }
#else
    private double _value;
    public double Value { get => _value; set => _value = Math.Max(0, value); }
#endif

See [skill:dotnet-multi-targeting] for comprehensive polyfill guidance.


Knowledge Sources

Feature guidance in this skill is grounded in publicly available language design rationale from:

  • C# Language Design Notes (Mads Torgersen et al.) -- Design decisions behind each C# version's features. Key rationale relevant to this skill: primary constructors (reducing boilerplate for DI-heavy services), collection expressions (unifying collection initialization syntax), field keyword (eliminating backing field ceremony), and extension blocks (grouping extensions by target type). Each feature balances expressiveness with safety -- e.g., primary constructor parameters are intentionally mutable captures (not readonly) to keep the feature simple; use explicit readonly fields when immutability is needed. Source: https://github.com/dotnet/csharplang/tree/main/meetings
  • C# Language Proposals Repository -- Detailed specifications and design rationale for accepted and proposed features. Source: https://github.com/dotnet/csharplang/tree/main/proposals
Note: This skill applies publicly documented design rationale. It does not represent or speak for the named sources.

References

适合场景

01

用户想查找某类 Agent Skill 时

02

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

03

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

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

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

能力 4

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

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

平台分布

Codex

34.42%
按下载量换算67

Claude

30.32%
按下载量换算59

Cursor

20.15%
按下载量换算39

Gemini CLI

9.93%
按下载量换算19

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

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

安装前确认

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

来源信息

继续浏览同类 Skills