プロパティ?フィールド?

プロパティ?フィールド?

おはようございます!!

PHP や JavaScript を使って Web システムを開発することが多いのですが、社内ツールを開発する際に C#を勉強する機会があり、その過程でイマイチその使い方や動作がわかりにくかったプロパティ、フィールドについて記事を書きたいと思います。

プロパティとフィールド

まずは用語の定義を見ていきます。

フィールド

フィールドとはクラスで宣言される任意の型の変数のことを指し、メンバ変数とも呼ばれます。

このフィールドは外部から参照されないようにカプセル化して使用されます。

フィールドへのアクセスは後述するプロパティからアクセスするように実装します。

プロパティ

クラス内のカプセル化されたフィールド(メンバ変数)を参照するために利用されます

プロパティはアクセサーという特殊なメソッドとも呼ばれ、フィールドの取得や変更などメソッドのようにロジックを実装する事もできます。

また、値を取得・変更する際に何らかの処理を割り込ませることも出来ます。

// フィールド
private int _count = 0;

// プロパティの書き方(内部で条件分岐したり何かロジックがある場合)
public int Count
{
    // getアクセサー(getterとも言う)
    // インスタンス化した後に、フィールドもしくはプロパティの値を取得しようとするとこっちの処理に入る
    get
    {
        return _count;
    }

    // setアクセサー(setterとも言う)
    // インスタンス化した後に、フィールドもしくはプロパティに値を代入するときはこっちの処理に入る
    set
    {
        // 値の変更時に、valueと言う変数に代入された値が格納される
        // 渡ってきた値が100以上だったら常に100をフィールドに代入する
        if (value >= 100)
        {
            _count = 100;
            return;
        }

        _count = value;
    }
}

他のクラスのフィールドを参照する際はプロパティ経由し、クラス内部からだと直接フィールドを参照する書き方が多いようですが、常にプロパティを経由して取得した方が分かりやすいと言う考え方もあるようです。

ただし、これが正解と言うものでもないので基本的に他のクラスのフィールドを参照する時にプロパティを使用すれば良いと思います。

プロパティのメリット

1 つのプロパティで値の取得・更新ができるので、Get メソッドや Set メソッドを用意しなくて良いという利点があります。

また、プロパティの set を記述しないことで読み取り専用のプロパティを実装することが出来ます。 反対に、get を記述しないことで書き込み専用のプロパティも実装できます。

// フィールド
private int _count = 0;

// 値を取得のみ
public int Count { get; }

自動実装プロパティ

値に対して内部ロジックが無い場合は、自動実装プロパティという機能を利用した書き方で private フィールドの記述を省略できます。

// 自動実装プロパティ
public int Count { get; set; }

外部から値の変更を許可したくない場合は以下のように記述します。

// 取得はパブリックに公開されて、値の設定はクラス内でしか出来ないカプセル化されたやり方
public int Count { get; private set; }

【余談】マイクロソフトのコード規約

今回の内容と直接関係ありませんが、マイクロソフトのコード規約には以下のように書かれていました。

機能名前付け規則
フィールドフィールドは頭にアンダーバーを付けてキャメルケースで記述
例:private IWorkerQueue \_workerQueue;
プロパティィ パスカルケースで記述
例:public IWorkerQueue WorkerQueue { get; init; }

こうして一定の基準を設けることで、複数人で開発する場合も分かりやすいコードを書くことが出来ます。

まとめ

C#でのプロパティとフィールドの違いをまとめると、

  • フィールド

    • アクセス修飾子は private でクラス内部から参照されるもの
    • カプセル化されていて、外部から参照出来なようにしたもの
    • 値を参照・書き換えをする際は、プロパティを経由する
  • プロパティ

    • アクセス修飾子は public で他のクラスからフィールドを参照できる
    • フィールドの値の参照・書き換えが出来る、アクセサー(特殊メソッド)とも呼ばれる
    • 何らかのロジックを挟むことが出来る
    • 読み取り、書き込み専用とすることも出来る

以上です!