From csharp
C# 核心开发规范:C# 12/.NET 8 语言标准、nullable reference types、pattern matching、primary constructors、collection expressions、Roslyn analyzers 静态分析。新建或审查 C# 项目时加载,是所有 C# 技能的基础依赖。
npx claudepluginhub lazygophers/ccplugin --plugin csharpThis skill uses the workspace's default tool permissions.
- **csharp:dev** - 开发阶段使用
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides MCP server integration in Claude Code plugins via .mcp.json or plugin.json configs for stdio, SSE, HTTP types, enabling external services as tools.
<Nullable>enable</Nullable>| 特性 | 说明 | 示例 |
|---|---|---|
| Primary constructors | 类/结构体参数化构造 | public class Service(IRepo repo) |
| Collection expressions | 统一集合初始化 | int[] nums = [1, 2, 3]; |
| Inline arrays | 固定大小栈数组 | [InlineArray(4)] struct Buffer { int _e; } |
| Alias any type | using 别名任何类型 | using Point = (int X, int Y); |
| Lambda defaults | Lambda 默认参数 | var add = (int x, int y = 1) => x + y; |
| Interceptors | 编译时方法替换 | source generator 场景 |
| 特性 | 说明 | 示例 |
|---|---|---|
| params collections | params 支持任何集合 | void Log(params ReadOnlySpan<string> msgs) |
| Lock object | 新的 Lock 类型 | private readonly Lock _lock = new(); |
| Extension types | 扩展类型(预览) | 替代传统 extension methods |
<Nullable>enable</Nullable>// ✅ C# 12 primary constructor(DI 场景)
public class UserService(IUserRepository repo, ILogger<UserService> logger)
{
public async Task<User?> GetAsync(int id, CancellationToken ct = default)
{
logger.LogDebug("Getting user {UserId}", id);
return await repo.FindAsync(id, ct);
}
}
// ✅ record 类型(DTO/值对象)
public record CreateUserRequest(string Name, string Email, int Age);
public record UserResponse(int Id, string Name, string Email);
// ❌ 传统冗余构造函数
public class UserService
{
private readonly IUserRepository _repo;
private readonly ILogger<UserService> _logger;
public UserService(IUserRepository repo, ILogger<UserService> logger)
{
_repo = repo;
_logger = logger;
}
}
// ✅ C# 12 collection expressions
int[] numbers = [1, 2, 3, 4, 5];
List<string> names = ["Alice", "Bob", "Charlie"];
Span<int> span = [1, 2, 3];
ReadOnlySpan<char> vowels = ['a', 'e', 'i', 'o', 'u'];
// ✅ Spread 运算符
int[] first = [1, 2, 3];
int[] second = [4, 5, 6];
int[] all = [..first, ..second]; // [1, 2, 3, 4, 5, 6]
// ❌ 传统初始化
var numbers = new int[] { 1, 2, 3, 4, 5 };
var names = new List<string> { "Alice", "Bob", "Charlie" };
// 项目文件启用
// <Nullable>enable</Nullable>
public class UserService(IUserRepository repo)
{
// ✅ 明确可空性
public string Name { get; set; } = "";
public string? Email { get; set; }
// ✅ 空条件运算符链
public string GetDisplayEmail() => Email?.ToLower() ?? "N/A";
// ✅ null 合并赋值
public List<User> GetUsers(List<User>? input) => input ??= [];
// ✅ 模式匹配空检查
public string Describe(User? user) => user switch
{
{ Name: var name, Email: not null } => $"{name} ({user.Email})",
{ Name: var name } => name,
null => "Unknown"
};
}
// ✅ .NET 8 Keyed Services
builder.Services.AddKeyedScoped<ICache, RedisCache>("redis");
builder.Services.AddKeyedScoped<ICache, MemoryCache>("memory");
public class UserService([FromKeyedServices("redis")] ICache cache) { }
// ✅ IOptions 模式
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("Smtp"));
public class EmailService(IOptions<SmtpSettings> options)
{
private readonly SmtpSettings _settings = options.Value;
}
<!-- .csproj 推荐配置 -->
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<!-- Roslyn analyzers -->
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.*" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.*" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.*" />
</ItemGroup>
# 格式化代码
dotnet format
# 运行 analyzers
dotnet build /p:TreatWarningsAsErrors=true
| AI 可能的理性化解释 | 实际应该检查的内容 |
|---|---|
| "传统构造函数可读性更好" | ✅ 简单 DI 类是否用 primary constructors? |
| "new List 已经够简洁" | ✅ 是否用 collection expressions? |
| "不启用 nullable 更方便" | ✅ 是否启用 <Nullable>enable</Nullable>? |
| "class 比 record 灵活" | ✅ DTO/值对象是否用 record? |
| "不需要 analyzers" | ✅ 是否配置 Roslyn + SonarAnalyzer? |
| "手动格式化就行" | ✅ 是否运行 dotnet format? |
[1, 2, 3]<Nullable>enable</Nullable>?.、??、??= 运算符!) 滥用dotnet format 格式化<TreatWarningsAsErrors>true</TreatWarningsAsErrors>