mcpField
.
.NET Conventions

.NET Conventions

github.com/exceptionless開発2.5k94 回インストール今日更新
リポジトリ

.NET Conventions について

.NET コードを保守する開発者向けの規約ガイドです。書式、命名、非同期処理、ログ、null 許容、検証を扱い、リソース破棄と依存性注入のパターンも示します。

主な機能

  1. 01書式と命名の規則
  2. 02非同期メソッドとキャンセルトークン
  3. 03構造化ログとスコープ
  4. 04null 許容とリソース破棄
  5. 05依存性注入と検証

活用シーン

  1. 01チーム内の .NET スタイル統一
  2. 02非同期呼び出しチェーンの統一
  3. 03ログへのコンテキスト追加
  4. 04null 処理と破棄の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/exceptionless/exceptionless --skill .net-conventions

インストール後、Claude Code で/.net-conventionsを入力して読み込まれたか確認します。

詳細

.NET の規約

スタイルと書式

  • .editorconfig のルールに厳密に従います
  • コミット前に dotnet format を実行します
  • 差分を最小限にする:必要な箇所のみ変更し、既存の書式と構造を維持します
  • 周囲のコードスタイルに正確に合わせます

命名規則

要素規則例
プライベートフィールド_camelCase_organizationRepository
パブリックメンバーPascalCaseGetByIdAsync
ローカル変数camelCaseorganizationId
定数PascalCaseMaxRetryCount
型パラメーターT プレフィックスTModel

書式ルール

  • インデント:4 個のスペース。タブは使用しません
  • 名前空間:ファイルスコープ形式(namespace Foo;)
  • Usings:名前空間の外側に記述します
  • 波括弧:1 行のブロックでも必ず使用します
  • #region は使用しない:#region/#endregion ディレクティブは使用しません。コードが隠れ、リファクタリングの妨げになるためです

非同期パターン

  • サフィックス:非同期メソッドには必ず Async サフィックスを付けます
  • CancellationToken:利用できる場合は、呼び出しチェーンを通して渡します
  • ValueTask:同期的に完了することが多いホットパスでは、ValueTask<T> を優先します
  • ConfigureAwait:ASP.NET Core では不要です
// From src/Exceptionless.Core/Services/UsageService.cs
public async Task SavePendingUsageAsync()
{
    var utcNow = _timeProvider.GetUtcNow().UtcDateTime;
    await SavePendingOrganizationUsageAsync(utcNow);
    await SavePendingProjectUsageAsync(utcNow);
}

構造化ログ

名前付きプレースホルダーを使ったメッセージテンプレートを使用します。値は文字列補間ではなく、引数として渡します。

// ✅ Correct: Named placeholders for structured data
_logger.LogInformation("Saving org ({OrganizationId}-{OrganizationName}) event usage",
    organizationId, organization.Name);

_logger.LogError(ex, "Error retrieving event post payload: {Path}", path);

_logger.LogWarning("Unable to parse user agent {UserAgent}. Exception: {Message}",
    userAgent, ex.Message);

// ❌ Wrong: String interpolation loses structure
_logger.LogInformation($"Saving org {organizationId}");
ExceptionlessState を使ったログスコープ

スコープを使用して、ブロック内のすべてのログエントリにコンテキストを追加します。

// From src/Exceptionless.Core/Jobs/EventPostsJob.cs
using var _ = _logger.BeginScope(new ExceptionlessState()
    .Organization(ep.OrganizationId)
    .Project(ep.ProjectId));

// All log entries in this scope automatically include org/project context
_logger.LogInformation("Processing event post");

より詳細なコンテキストを得るため、タグとプロパティを追加します。

using (_logger.BeginScope(new ExceptionlessState()
    .Organization(organization.Id)
    .Tag("Delete")
    .Tag("Bot")))
{
    _logger.LogInformation("Removing bot events");
}

Null 許容参照型

  • 全体を通して null 許容注釈を遵守します
  • null 許容に関する警告はエラーとして扱います
  • null 許容型には ? サフィックスを使用します
public async Task<User?> FindUserAsync(string? email)
{
    if (string.IsNullOrWhiteSpace(email))
        return null;

    return await _repository.FindByEmailAsync(email);
}

リソースの破棄

// Prefer using declarations
using var stream = File.OpenRead(path);

// Async disposal
await using var connection = await CreateConnectionAsync();

コンストラクターインジェクション

読み取り専用フィールドを使ったコンストラクターインジェクションを優先します。

// From src/Exceptionless.Core/Services/UsageService.cs
public class UsageService
{
    private readonly IOrganizationRepository _organizationRepository;
    private readonly ICacheClient _cache;
    private readonly TimeProvider _timeProvider;
    private readonly ILogger _logger;

    public UsageService(
        IOrganizationRepository organizationRepository,
        ICacheClient cache,
        TimeProvider timeProvider,
        ILoggerFactory loggerFactory)
    {
        _organizationRepository = organizationRepository;
        _cache = cache;
        _timeProvider = timeProvider;
        _logger = loggerFactory.CreateLogger<UsageService>();
    }
}

検証パターン

入力検証

早めに検証し、問題があれば速やかに失敗させます。

public async Task<ActionResult> ProcessAsync(string id)
{
    if (string.IsNullOrEmpty(id))
        return BadRequest("Id is required");

    var entity = await _repository.GetByIdAsync(id);
    if (entity is null)
        return NotFound();

    // Continue processing
}
ドメイン検証

検証パターンについては、backend-architecture を参照してください(ドメインモデルには FluentValidation、API リクエストには MiniValidator を使用します)。

コメント