一意な 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回
ディスカッション
コメント一覧
まだ、コメントがありません