.NET/C#のコーディング規約、命名規則、レイアウト、C# 12/13/14の最新機能活用ガイドラインを定義する。C#/.NETコード作成時、クラス・メソッド命名時、コードフォーマット時、またはユーザーがコーディング規約、命名規則、C#ベストプラクティス、Primary Constructors、Collection Expressions、field キーワードに言及した際に使用する。
Provides C#/.NET coding conventions, naming rules, and modern feature guidance (C# 12-14). Triggered when creating C# code or when users ask about conventions, naming, best practices, Primary Constructors, Collection Expressions, or the `field` keyword.
/plugin marketplace add RevTechStudio/rts-plugins/plugin install rts-foundation@rts-pluginsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
このSkillは、開発されるすべての.NETプロジェクトに適用されるコーディング規約を定義する。.NET 8以降の最新機能(C# 12/13/14、.NET 8/9/10)を積極的に活用し、可読性、保守性、パフォーマンスの高いコードを実現することを目的とする。
このSkillは以下の範囲をカバーする:
_field)の使用は絶対に禁止する.NET 8以降の各バージョンで導入された主要機能を積極的に活用する。古いバージョンとの互換性が必要な場合を除き、常に最新の機能を優先的に使用する。
良い例:
public class Person(string name, int age)
{
public string Name => name;
public int Age => age;
public void Display()
{
Console.WriteLine($"{name} is {age} years old");
}
}
悪い例:
public class Person
{
private string name;
private int age;
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
public string Name => name;
public int Age => age;
}
良い例:
int[] array = [1, 2, 3, 4, 5];
List<string> list = ["one", "two", "three"];
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
// スプレッド演算子で結合
int[] combined = [..row0, ..row1];
良い例:
var incrementBy = (int source, int increment = 1) => source + increment;
Console.WriteLine(incrementBy(5));
Console.WriteLine(incrementBy(5, 3));
良い例:
using Point = (int x, int y);
using ProductList = System.Collections.Generic.List<(string Name, decimal Price)>;
Point origin = (0, 0);
ProductList products = [("Product1", 100m), ("Product2", 200m)];
params修飾子が配列以外のコレクション型でも使用可能になったList<T>, Span<T>, ReadOnlySpan<T>, IEnumerable<T>などで使用できる良い例:
public void ProcessItems(params List<string> items)
{
foreach (var item in items)
{
Console.WriteLine(item);
}
}
// メモリ効率が重要な場合
public void ProcessData(params ReadOnlySpan<int> data)
{
foreach (var value in data)
{
Process(value);
}
}
System.Threading.Lock型を使用して、より高速なスレッド同期を実現するMonitorベースのロックより高速良い例:
private readonly Lock lockObject = new();
public void UpdateData()
{
lock (lockObject)
{
// クリティカルセクション
}
}
悪い例:
// 従来のobjectベースのロック(C# 13では推奨されない)
private readonly object lockObject = new();
public void UpdateData()
{
lock (lockObject)
{
// クリティカルセクション
}
}
良い例:
// 定義部分
public partial class DataModel
{
public partial string Name { get; set; }
}
// 実装部分
public partial class DataModel
{
private string name;
public partial string Name
{
get => name;
set => name = value ?? throw new ArgumentNullException(nameof(value));
}
}
^演算子が使用可能になった良い例:
var countdown = new TimerBuffer
{
buffer =
{
[^1] = 0,
[^2] = 1,
[^3] = 2
}
};
ref struct型がインターフェースを実装できるようになったref structを使用できるようになった(allows ref struct制約)良い例:
public ref struct SpanWrapper<T> : IEnumerable<T>
{
private Span<T> span;
public IEnumerator<T> GetEnumerator()
{
foreach (var item in span)
{
yield return item;
}
}
}
良い例:
extension<TSource>(IEnumerable<TSource> source)
{
public bool IsEmpty => !source.Any();
public int Count => source.Count();
}
fieldキーワードを使用して明示的なバッキングフィールドを削減する良い例:
// C# 14のfieldキーワードを使用
public string Name
{
get;
set => field = value ?? throw new ArgumentNullException(nameof(value));
}
// やむを得ず明示的なバッキングフィールドが必要な場合もアンダースコアなし
private string name;
public string Name
{
get => name;
set => name = value ?? throw new ArgumentNullException(nameof(value));
}
悪い例:
// アンダースコアプレフィックスは絶対に禁止
private string _name;
public string Name
{
get => _name;
set => _name = value ?? throw new ArgumentNullException(nameof(value));
}
?.を使用してnullチェックを簡潔に記述する良い例:
customer?.Order = GetCurrentOrder();
悪い例:
if (customer != null)
{
customer.Order = GetCurrentOrder();
}
Span<T>とReadOnlySpan<T>を活用する良い例:
public class CustomerOrder
{
public string OrderId { get; set; }
public void ProcessOrder() { }
}
良い例:
public class OrderProcessor
{
// アンダースコアなし
private string customerName;
// アンダースコアなし
private int orderCount;
public void ProcessOrder(string orderId)
{
var customerName = GetCustomerName(orderId);
string processedResult = Process(customerName);
}
}
悪い例:
public class OrderProcessor
{
// アンダースコアプレフィックスは絶対に禁止
private string _customerName;
// アンダースコアプレフィックスは絶対に禁止
private int _orderCount;
}
Iを使用する良い例:
public interface IOrderProcessor
{
void Process(Order order);
}
Tを使用する良い例:
public class Repository<TEntity> where TEntity : class
{
public void Add(TEntity entity) { }
}
良い例:
public void ProcessOrder(Order order)
{
if (order != null)
{
order.Process();
}
}
// 1行でも中括弧を使用する
if (isValid)
{
Execute();
}
for (int i = 0; i < 10; i++)
{
Process(i);
}
悪い例:
// 中括弧の省略は禁止
if (isValid)
Execute();
// 中括弧の省略は禁止
for (int i = 0; i < 10; i++)
Process(i);
// 中括弧の省略は禁止
if (order != null) order.Process();
良い例:
public class Order
{
public string OrderId { get; set; }
public void Process()
{
var result = Validate();
Execute(result);
}
private bool Validate()
{
return OrderId != null;
}
}
良い例:
namespace YourProject.Orders;
public class OrderProcessor
{
// 実装
}
悪い例:
namespace YourProject.Orders
{
public class OrderProcessor
{
// 実装
}
}
良い例:
using System;
using System.Collections.Generic;
using System.Linq;
namespace YourProject.Orders;
string, int, bool)を使用するSystem.String, System.Int32)は使用しない良い例:
string name = "John";
int count = 10;
bool isValid = true;
悪い例:
String name = "John";
Int32 count = 10;
Boolean isValid = true;
varを使用する良い例:
// 明白
var orders = new List<Order>();
// 明白
var customer = GetCustomer();
// 組み込み型は明示
int count = 10;
// 組み込み型は明示
string name = "John";
悪い例:
// 組み込み型でvarは避ける
var count = 10;
// 組み込み型でvarは避ける
var name = "John";
良い例:
string message = $"Order {orderId} processed successfully";
悪い例:
string message = "Order " + orderId + " processed successfully";
StringBuilderを使用する良い例:
var builder = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
builder.Append($"Line {i}\n");
}
良い例:
string json = """
{
"name": "John",
"age": 30
}
""";
良い例:
var customer = new Customer
{
Name = "John",
Email = "john@example.com"
};
System.Exceptionではなく具体的な例外をキャッチする良い例:
try
{
ProcessOrder(order);
}
catch (ArgumentNullException ex)
{
Logger.Error("Order is null", ex);
}
悪い例:
try
{
ProcessOrder(order);
}
catch (Exception ex) // 一般的すぎる
{
Logger.Error("Error", ex);
}
usingステートメントを使用する良い例:
using var connection = new SqlConnection(connectionString);
connection.Open();
// 処理
悪い例:
SqlConnection connection = null;
try
{
connection = new SqlConnection(connectionString);
connection.Open();
// 処理
}
finally
{
connection?.Dispose();
}
良い例:
var activeCustomers = from customer in customers
where customer.IsActive
select customer;
where句を使用して早期にデータをフィルタリングする良い例:
var result = customers
.Where(c => c.IsActive)
.Select(c => c.Name)
.ToList();
良い例:
var query = from customer in customers
where customer.IsActive
select customer;
良い例:
button.Click += (s, e) => ProcessClick();
良い例:
TryParse<int> parse = (text, out result) => int.TryParse(text, out result);
//を使用する良い例:
// 顧客の注文を処理する
ProcessOrder(order);
var processor = new OrderProcessor();
// 注文を実行する
var result = processor.ProcessOrder(order);
悪い例:
ProcessOrder(order); // 顧客の注文を処理する(コードと同じ行は禁止)
var result = processor.ProcessOrder(order); // 注文を実行する(コードと同じ行は禁止)
var processor = new OrderProcessor();
// この行の前に空行がない(悪い例)
var result = processor.ProcessOrder(order);
良い例:
/// <summary>
/// 指定された注文を処理する
/// </summary>
/// <param name="order">処理する注文</param>
/// <returns>処理結果</returns>
public bool ProcessOrder(Order order)
{
// 実装
}
良い例:
var result = OrderProcessor.ProcessOrder(order);
悪い例:
var processor = new OrderProcessor();
// 静的メソッドをインスタンス経由で呼び出すのは誤解を招く
var result = processor.ProcessOrder(order);
必須ルール:
C# 12以降の機能:
C# 13以降の機能:
C# 14以降の機能:
fieldキーワードを使用してバッキングフィールドを簡潔に記述している基本規則:
string, int)を使用しているvarを適切に使用している(型が明白な場合のみ)usingステートメントを使用しているThis skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.