一意な ID を自動生成して読み取り専用で公開する ― Player クラス実装パターン

背景と目的

  • ゲーム開発や業務アプリでは、プレイヤー・トランザクション・注文などを一意に識別する ID が必要になる。
  • この ID は 生成後に変更されてはならない
  • C# では readonly フィールドと 式形式プロパティを組み合わせることで、簡潔かつ安全に実装できる。

完成コード

public class Player
{
    // ❶ インスタンス生成時に一意な ID を確定
    private readonly string _id = Guid.NewGuid().ToString();

    // ❷ 読み取り専用で公開(式形式プロパティ)
    public string Id => _id;     // C# 6 以降
}

詳細解説

1. readonly フィールドで不変を保証

private readonly string _id = Guid.NewGuid().ToString();
  • readonly を付けると
    • フィールドは「宣言時」または「コンストラクタ内」でしか代入できない。
    • それ以降は再代入不可なので、ID の不変性をコードで強制できる。
  • 誤って _id = “ABC"; と書くとコンパイル エラーになり、安全性が高まる。

2. Guid.NewGuid() で一意な識別子を生成

  • Guid は 128 ビット(16 バイト)の一意識別子
  • 重複確率は極めて低く、ローカル生成でもほぼ衝突しないため、
    • DB のプライマリ キー
    • ネットワーク越しの識別子
    • テスト用ダミー データに広く利用される。
  • .ToString() で人が扱いやすい文字列へ変換。

3. 式形式プロパティでシンプルに公開

public string Id => _id;
  • 式形式(expression-bodied)プロパティは、
public string Id
{
    get { return _id; }
}

の短縮形。

  • set アクセサを持たないので、外部からの書き換えを禁止
  • C# 6(Visual Studio 2015)以降で利用可能。

4. static を付けない理由

  • static readonly にするとクラス全体で 1 つの ID を共有してしまい、
    • どの Player インスタンスも同じ ID になる。
  • インスタンス固有の ID を持たせたい場合は static を付けないのが正解。

利用シナリオ例

var alice = new Player();
var bob   = new Player();

Console.WriteLine(alice.Id); // 例) 3f01e388-9cb2-4f95-961a-84a001fb9c5d
Console.WriteLine(bob.Id);   // 例) 4cf8d1c0-2c1a-45d5-bf8b-1c9e31c80df8
Console.WriteLine(alice.Id == bob.Id); // False
  • セーブデータ: プレイヤーを ID で紐づけて保存/復元。
  • ネットワーク通信: クライアント間でオブジェクトを区別。
  • デバッグ/ログ: エラー発生時にどのインスタンスが原因か特定。

よくある質問

質問回答
コンストラクタ内で代入しても良い?可能。readonly フィールドなので「宣言時」または「コンストラクタ」が選べる。
C# 9 の init プロパティを使う選択肢は?public string Id { get; init; } = Guid.NewGuid().ToString(); と書く方法もある。ただし init はオブジェクト初期化子経由で書き換えできるため、完全不変を徹底したい場合は readonly フィールド の方が安全。
ID を数値で持ちたいlong や int の連番を使う場合は、DB の自動採番や Interlocked.Increment などで衝突を防ぐ設計が必要。

まとめ

  • readonly フィールド + Guid.NewGuid() で一度しか設定できない一意 ID を作成。
  • 式形式プロパティで読み取り専用として公開し、記述を簡潔化。
  • static を付けないことで インスタンスごとにユニーク な ID を保証。

このパターンは、ゲーム オブジェクトの識別子から業務システムのトランザクション ID まで幅広く応用できる。コード例をそのままコピーして、自身のプロジェクトに組み込んでみよう。

訪問数 3 回, 今日の訪問数 1回

C#

Posted by hidepon