C#入門⑲ フィールドとプロパティ ── データを、安全に扱う
前回は「クラス(データと処理をまとめた設計図)」をやりました。
今回は、クラスが持つデータの話。フィールドとプロパティです。少し細かい話ですが、データを「安全に」扱うための、大事な仕組みです。
フィールドはクラスが持つデータそのもの、プロパティはそれを安全に出し入れする窓口です。
フィールド ── クラスが持つデータ
前回、クラスの中に書いたこれ。
class Person
{
public string Name;
public int Age;
}
この Name や Age のような、クラスが持つデータのことを、フィールドと呼びます。前回から、もう使っていたんですね。
フィールドは、そのまま読み書きできます。
Person taro = new Person();
taro.Age = 20; // 書き込み
Console.WriteLine(taro.Age); // 読み出し
便利ですが、ここに、ちょっとした問題があります。
そのままだと、変な値も入ってしまう
フィールドは、そのままだとどんな値でも入ってしまいます。
taro.Age = -5; // 年齢がマイナス?
taro.Age = 9999; // 年齢が9999歳?
ありえない値ですが、プログラム上は止められません。年齢に -5 や 9999 が入っても、エラーにならず、そのまま通ってしまう。
これは、けっこう危険です。おかしなデータが紛れ込むと、後でバグの原因になります。
「おかしな値が入らないように、見張りをつけたい」。そこで登場するのが、プロパティです。
プロパティ ── データの出入りを見張る窓口
プロパティは、データを出し入れするときに、間に入ってチェックする窓口です。
料理でいうなら、受付係のようなもの。「この食材、傷んでないか確認してから、中に入れますね」と、間でチェックしてくれる人です。
書き方を見てみます。年齢に、変な値が入らないようにしたプロパティです。
class Person
{
private int age; // 実際のデータ(外から直接さわれない)
public int Age // 窓口(プロパティ)
{
get { return age; } // 読むとき
set
{
if (value >= 0) // 0以上のときだけ
{
age = value; // 受け入れる
}
}
}
}
少し長いですが、ポイントだけ押さえれば大丈夫です。
private int age… 本当のデータ。privateなので外から直接さわれないpublic int Age… 外から使う窓口(プロパティ)get… 値を読むときの処理set… 値を書くときの処理。ここでチェックできるvalue… 外から入れようとした値が、ここに入っている
set の中で「0以上のときだけ受け入れる」とチェックしているので、マイナスの値は弾かれます。
taro.Age = 20; // 0以上なのでOK
taro.Age = -5; // 弾かれる(age は変わらない)
使う側は、フィールドのときとまったく同じ書き方です。でも裏で、こっそり見張りが働いている。これがプロパティの便利なところです。
なぜ「直接さわれない」ようにするのか
ここで、第17回(スコープ)で少し触れた public と private が効いてきます。
public… 外から使えるprivate… 外から使えない(クラスの中だけ)
本当のデータ age を private にして隠し、public のプロパティ Age だけを窓口として開ける。
こうすると、外からは必ず窓口(プロパティ)を通ることになります。窓口でチェックしているので、変な値は入れません。
データを隠して、決まった窓口だけ開ける。この考え方をカプセル化と呼びます。オブジェクト指向の、大事な考え方のひとつです。
短く書く方法もある
毎回こんなに長く書くのは大変です。チェックがいらない単純な場合は、短く書けます。
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
{ get; set; } と書くだけ。「読み書きできる窓口」を、簡単に用意できます。実際の開発では、この短い書き方をよく使います。
まずは「フィールドは生のデータ、プロパティはチェックできる窓口」という考え方をつかんでおけば十分です。
つまずきポイント
混乱しやすいのが、フィールドとプロパティの名前です。
慣習として、
- フィールド(隠す方)… 小文字で始める(
age) - プロパティ(窓口)… 大文字で始める(
Age)
名前を変えて区別します。同じ「年齢」でも、age(生データ)と Age(窓口)は別物だと意識すると、混乱しません。
まとめ
フィールドは生のデータ、プロパティはそれを安全に扱う窓口。
- フィールド … クラスが持つデータそのもの
- プロパティ …
get(読む)とset(書く)で、出入りをチェックできる窓口 - データを
privateで隠し、窓口だけ開けるのが カプセル化 - 単純なら
{ get; set; }で短く書ける
次回は、クラスの中に「処理」を持たせる、クラスの中のメソッド です。

