C#におけるフィールドとプロパティの使い分け

概要

C# ではクラス内でデータを保持する際に、フィールドプロパティを利用することができます。本資料では、それぞれの特徴や利点、使い分けについて解説します。


フィールド

特徴

  • データを直接保持する変数
  • クラス内部でのみ使用することが推奨される(通常、privateに設定)。
  • 外部アクセスの制御や値のバリデーションは、フィールド単体では実現できない。
バリデーションとは

「不正な値(負のHPやダメージ)を防ぎ、データの一貫性と安全性を保証するためのロジックです

メリット

  • シンプルで記述量が少ない。
  • データの格納と取得に特化している。

デメリット

  • 値の変更や取得に対する制御が難しい。
  • 外部から直接アクセスされる場合、データの整合性が崩れる可能性がある。

プロパティ

特徴

  • フィールドへのアクセスを制御するインターフェイス。
  • get(取得)およびset(設定)のアクセサを持つ。
  • 外部アクセスの制御やバリデーションを含めることができる。

メリット

  • 値の取得や変更に特定のロジックを追加できる。
  • フィールドへのアクセス方法を統一し、一貫性を保つ。
  • 実装を変更しても外部のコードに影響を与えないため、拡張性が高い。

デメリット

  • 初期段階では記述が増える。
  • 単純なデータ保持の場合にはやや冗長。

フィールドとプロパティの使い分け

項目フィールドプロパティ
用途内部でのみデータを保持外部に公開するデータを管理
アクセス制御不可能get/setで可能
バリデーションコンストラクタやメソッドで実現プロパティ内で実現可能
記述量少ない多い(状況による)
拡張性低い高い

実装例

1. フィールドを利用した実装

public class Player
{
    private int hp;

    public Player(int hp)
    {
        if (hp < 0)
        {
            throw new ArgumentException("HP cannot be negative.");
        }
        this.hp = hp; // フィールドに直接代入
    }
}
  • フィールドに直接代入するシンプルな設計ですが、制限ロジックを追加する場合、コンストラクタや他のメソッドに記述する必要があります。
  • フィールドへのアクセスや変更を管理する一貫した方法は提供されません。

2. プロパティを利用した実装

public class Player
{
    private int hp;

    public Player(int hp)
    {
        Hp = hp; // プロパティを通じて代入
    }

    public int Hp
    {
        get => hp;
        set
        {
            if (value < 0)
            {
                throw new ArgumentException("HP cannot be negative.");
            }
            hp = value;
        }
    }
}
  • プロパティを使用することで、値の設定時にバリデーションを適用できます。
  • フィールドの値を一貫して管理できるため、後々の変更や拡張が容易です。

フィールドとプロパティの具体的な比較

フィールドの長所と短所

長所:

  • 記述が少なく、シンプル。
  • 値をそのまま保持するのに適している。

短所:

  • 値のバリデーションや制御が難しい。
  • 直接公開すると、外部からの不正な値の変更に弱い。

プロパティの長所と短所

長所:

  • 値の設定時にバリデーションを適用できる。
  • 値の取得や変更時にロジックを挿入できる。
  • クラスの内部外部を問わず、一貫性を保てる。

短所:

  • 初期段階では記述量が多く感じる。
  • 簡単なデータ保持では過剰に感じる場合もある。

推奨される書き方

以下のコード例は、プロパティを活用した推奨スタイルです。

プロパティを用いた安全な実装

public class Player
{
    private int hp;

    public Player(int hp)
    {
        Hp = hp; // プロパティを使用
    }

    public int Hp
    {
        get => hp;
        private set
        {
            if (value < 0)
            {
                throw new ArgumentException("HP cannot be negative.");
            }
            hp = value;
        }
    }

    public void TakeDamage(int damage)
    {
        if (damage < 0)
        {
            throw new ArgumentException("Damage cannot be negative.");
        }
        Hp = Math.Max(0, Hp - damage); // HPが負の値にならないよう制御
    }
}

まとめ

  • フィールドは単純なデータ保持に向いていますが、外部からの直接アクセスを避けるためにprivateとして利用するべきです。
  • プロパティは値の管理や制御を含めた柔軟な実装が可能であり、特に実務ではプロパティを利用する設計が推奨されます。
  • 一貫性、拡張性、安全性を重視する場合は、プロパティを通じてデータを管理するスタイルを採用してください。

この資料を参考に、C#での設計や実装スキルを向上させましょう!