プロパティが誕生した背景
オブジェクト指向の中で重要な考え方として「カプセル化」というものがあります。 カプセル化とは、データとそれを操作するメソッドを一つのモジュールとしてまとめることであり、 データはそのメソッドを通して操作するようにしなければいけません。
そのため、オブジェクト指向プログラミングでは、 フィールドとその値を取得・設定するための Getter および Setter を作成し、 フィールドは private にして外部から見えないようにすべきです。 これを単純に実装すると、例えば次のようなコードになるでしょう。
class Person { private int age; // データを保持する変数 (フィールド) public void SetAge(int age) { this.age = age; } public int GetAge() { return age; } }
基本にとても忠実です。素晴らしい。 でも、下記のようにちょっとイケてないです。
見た目がイケてない
1つのフィールドに対して、Get/Setという2つのメソッドを書くことになるし、 冗長で打鍵量も多いです。 前述の例だと、「Age」という文字列を 2 回も打たなければならないし、 メソッドなので引数リストも書かなくちゃいけないです。
外部から使うときもイケてない
クラス外からフィールドを変更するには、 これらの Getter/Setter を通さないといけないです。 例えば次のように取得・設定することになります。
person.SetAge(42); int age = person.GetAge();
クラスの利用者にしてみれば、 インスタンス内のデータを取得したり設定したりしたいだけなので、 ぶっちゃけフィールドに直接アクセスできた方が楽です。
// age への直接アクセスはダメだけど、こう書けた方がスッキリするよね person.age = 42; int age = person.age;
プロパティとは
「プロパティ」は、前述のような背景があり生まれた C# の構文です。
アクセス修飾子 型 名前 { get { // Getter の処理 } set { // Setter の処理 } }
例えば、前述の「年齢の取得・設定」の例は次のようになります。
class Person { private int age; public int Age { get { return age; } set { age = value; } } }
利用側は次のようになります。
Age
という変数に直接アクセスしているように見えますが、
実際には Getter や Setter が呼ばれます。
person.Age = 42; int age = person.Age;
このように、「クラスの実装者にとってはメソッドだけど、 クラスの利用者にとってはデータに直接アクセスしているように見える」 というのがプロパティです。
プロパティの導入によって、
- Getter/Setter がひとまとまりになり、冗長な文字列も書かなくてよくなります。
- 利用側からは直接フィールドの値を取得・設定しているように見え、スッキリします。
C#では、インスタンス内のデータを取得したり設定したりするときに、 通常のメソッドの形で Getter/Setter を用意することはまず無いです。 プロパティを作るようにしましょう。
なお、この例の age
のようなフィールドのことを、
バッキングフィールド (backing field) と言います。
クラス外に見せるプロパティに対して、
「そのプロパティの背後にあるフィールド」
という意味合いからそう呼ばれているのだと思います。
自動実装プロパティ
前述のように、単に値の取得だけをする Getter や、 値の設定だけをする Setter を、プロパティとして用意したとしても、 結構な行数を必要としてしまいます。
private int age; public int Age { get { return age; } set { age = value; } }
C# のインデント方式では、ブロックの始まりのカッコ「{」だけでも改行をするのが一般的ですので、 単に取得・設定するだけでも、12行も使うことになってしまいます。
単に取得・設定するだけのコードであれば、 コンパイラに自動で生成させちゃいましょう、 ってことで上記のコードは下記のように省略することができます。 これは自動実装プロパティと呼ばれます。
public int Age { get; set; }
この 1 行のコードと、前述の 12 行のコードは、同じ意味です。 自動実装プロパティを使うと、コンパイラによって、 自動でバッキングフィールドが作られ、その値を取得・設定するようなコードも自動生成されます。