ワンクリックで
csharp-idioms
Use when applying modern C# idioms — records, pattern matching, primary constructors, collection expressions.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Use when applying modern C# idioms — records, pattern matching, primary constructors, collection expressions.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Use when adding caching to .NET APIs or optimizing response times with distributed cache, output cache, or ETags.
Use when configuring API response formats, custom formatters, or Accept header handling.
Use when building controller-based REST APIs with action results, model binding, or MediatR integration.
Use when creating RESTful API controllers with MediatR dispatch and ProblemDetails error responses.
Use when designing gRPC services, proto files, or adding gRPC-Web or JSON transcoding.
Use when building minimal API endpoints with route groups, filters, or TypedResults.
| name | csharp-idioms |
| description | Use when applying modern C# idioms — records, pattern matching, primary constructors, collection expressions. |
| metadata | {"category":"core","agent":"dotnet-architect","alwaysApply":true} |
| Feature | Minimum | C# Version |
|---|---|---|
| File-scoped namespaces | .NET 6 | C# 10 |
required modifier | .NET 7 | C# 11 |
| Primary constructors | .NET 8 | C# 12 |
| Collection expressions | .NET 8 | C# 12 |
field keyword | .NET 10 | C# 14 |
| Extension types | .NET 10 | C# 14 |
// PREFER — file-scoped (one less indent level)
namespace {Company}.{Domain}.Features.Orders;
public sealed class OrderService { }
// Immutable DTO
public sealed record OrderResponse(Guid Id, string CustomerName, decimal Total);
// Value object with behavior
public sealed record Money(decimal Amount, string Currency)
{
public Money Add(Money other)
{
if (Currency != other.Currency)
throw new InvalidOperationException("Cannot add different currencies");
return this with { Amount = Amount + other.Amount };
}
}
// Record struct for lightweight value types
public readonly record struct OrderId(Guid Value)
{
public static OrderId New() => new(Guid.NewGuid());
}
// Service with DI — no field declarations needed
public sealed class OrderService(
IOrderRepository repository,
ILogger<OrderService> logger)
{
public async Task<Order?> GetAsync(Guid id, CancellationToken ct)
{
logger.LogInformation("Fetching order {OrderId}", id);
return await repository.FindAsync(id, ct);
}
}
int[] numbers = [1, 2, 3];
List<string> merged = [..existing, ..additional, "extra"];
ReadOnlySpan<byte> bytes = [0x01, 0x02, 0x03];
// Empty collection
List<Order> orders = [];
// Switch expression
string label = order.State switch
{
OrderState.Pending when order.Total > 1000 => "Requires approval",
OrderState.Pending => "Awaiting processing",
OrderState.Shipped => "In transit",
OrderState.Delivered => "Complete",
_ => "Unknown"
};
// Property pattern
if (order is { Status: OrderStatus.Shipped, Total: > 500 })
ApplyDiscount(order);
// List pattern (C# 12)
var result = args switch
{
[var cmd, ..var rest] => ProcessCommand(cmd, rest),
[] => ShowHelp()
};
// is null / is not null (prefer over == null)
if (order is not null)
Process(order);
// Seal classes not designed for inheritance
public sealed class OrderValidator
{
// Expression body for single-line methods
public bool IsValid(Order order) => order.Items.Count > 0 && order.Total > 0;
// Expression body for properties
public string Name => nameof(OrderValidator);
}
namespace {Company}.{Domain}.Features.Orders;
public sealed class OrderService
{
// PascalCase: types, methods, properties, constants
private const string DefaultCurrency = "USD";
// _camelCase: private fields
private readonly IOrderRepository _repository;
// camelCase: parameters and locals
public async Task<OrderResponse?> GetOrderAsync(Guid orderId)
{
var order = await _repository.FindAsync(orderId);
return order is null ? null : MapToResponse(order);
}
// Async suffix on async methods
private static OrderResponse MapToResponse(Order order) => new(
Id: order.Id,
CustomerName: order.CustomerName,
Total: order.Total);
}
// Auto-property with validation — no backing field declaration
public string Name
{
get => field;
set => field = value?.Trim() ?? throw new ArgumentNullException(nameof(value));
}
== null instead of is null<LangVersion> in .csproj or Directory.Build.props<TargetFramework> for net8.0, net9.0, net10.0.cs files for primary constructor usagerecord keyword usage in model/DTO files.editorconfig for naming and style rules_camelCase vs camelCase).editorconfig if missing to enforce style rules:[*.cs]
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_var_for_built_in_types = false:suggestion
csharp_style_prefer_pattern_matching = true:suggestion
dotnet_naming_rule.private_fields_should_be_camel_case.severity = warning
| Scenario | Recommendation |
|---|---|
| New DTO / response type | Use record |
| Service class with DI | Use primary constructor (.NET 8+) |
| Multiple type checks | Use switch expression with patterns |
| Null check | Use is null / is not null |
| New file | Use file-scoped namespace |
| Lightweight ID type | Use readonly record struct |