クラスのデータと「カプセル化」
C#のクラスは、データ(状態)と振る舞い(メソッド)を一つにまとめた設計図です。クラスが持つデータを「フィールド(メンバー変数)」として定義できますが、これをpublic(公開)にしてしまうと、クラスの外部から誰でも自由に値を書き換えられるようになってしまいます。
public class User
{
public string Name; // public フィールド(非推奨)
}
// 外部から自由に書き換え可能
var user = new User();
user.Name = null; // 不正な値や null も設定できてしまう
このような無制御なアクセスを防ぎ、クラスの内部状態を保護するオブジェクト指向の原則を「カプセル化」と呼びます。
C#では、このカプセル化をスマートに実現するために、フィールドをprivate(非公開)にし、そのフィールドに対する読み書きの「窓口」として「プロパティ(Property)」を定義するのが標準的な方法です。
自動実装プロパティ ({ get; set; })
プロパティを定義する最も簡単で一般的な方法が「自動実装プロパティ(Auto-Implemented Property)」です。
構文: public T MyProperty { get; set; }
{ get; set; }: この構文を使用すると、C#コンパイラが、このプロパティの値を格納するためのprivateな「バッキングフィールド(Backing Field)」を内部的に自動生成してくれます。get(ゲッター): プロパティの値を読み取る(取得する)ために呼び出されます。set(セッター): プロパティに値を書き込む(設定する)ために呼び出されます。
開発者は、privateなフィールドを明示的に宣言することなく、publicなプロパティ(窓口)だけを定義できます。
コード例1:基本的なプロパティの使い方
Product(商品)クラスを定義し、Code(商品コード)とPrice(価格)という2つのプロパティを持つ例です。
using System;
/// <summary>
/// 商品を表すクラス
/// </summary>
public class Product
{
// 外部に公開するプロパティ (読み書き可能)
// 内部に 'Code' の値を保持する private フィールドが自動作成される
public string Code { get; set; }
// 内部に 'Price' の値を保持する private フィールドが自動作成される
public decimal Price { get; set; }
}
public class PropertyBasicExample
{
public static void Main()
{
// 1. Product クラスのインスタンスを生成
var item = new Product();
// 2. 'set' が呼び出され、値が設定される
item.Code = "SKU-001";
item.Price = 1500m;
// 3. 'get' が呼び出され、値が読み取られる
Console.WriteLine($"商品コード: {item.Code}");
Console.WriteLine($"価格: {item.Price:N0}円");
// 4. 値の更新 ('set' が再度呼び出される)
item.Price = 1800m;
Console.WriteLine($"改定価格: {item.Price:N0}円");
}
}
出力結果:
商品コード: SKU-001
価格: 1,500円
改定価格: 1,800円
応用:読み取り専用プロパティ ({ get; private set; })
プロパティは、getやsetに個別のアクセス修飾子(privateなど)を指定することで、アクセスレベルを制御できます。
最も一般的なパターンが{ get; private set; }です。
get;:public(デフォルト)。誰でも値を読み取ることができます。private set;:private。値の書き込みは、このクラスの内部(例: コンストラクタやメソッド)からしか許可されません。
これにより、外部からは変更不可能な「読み取り専用プロパティ」を簡単に作成できます。
コード例2:読み取り専用プロパティ
ユーザーID(UserId)のように、一度設定されたら外部からは変更されたくない値を扱う例です。
using System;
public class UserAccount
{
// UserId は外部からは読み取り専用
public int UserId { get; private set; }
// UserName は外部からも変更可能
public string UserName { get; set; }
// コンストラクタ (クラス内部)
public UserAccount(int id, string initialName)
{
// 'private set' であっても、クラス内部からは書き込み可能
this.UserId = id;
this.UserName = initialName;
}
// クラス内部のメソッドからも書き込み可能
// public void ChangeId(int newId) { this.UserId = newId; }
}
public class ReadOnlyPropertyExample
{
public static void Main()
{
var user = new UserAccount(101, "Alice");
// 'get' は public なので読み取り可能
Console.WriteLine($"ユーザーID: {user.UserId}");
Console.WriteLine($"ユーザー名: {user.UserName}");
// 'set' は private なので、外部からの書き込みはコンパイルエラー
// user.UserId = 102; // コンパイルエラー!
// 'set' が public なプロパティは変更可能
user.UserName = "Alice (Updated)";
Console.WriteLine($"更新後の名前: {user.UserName}");
}
}
出力結果:
ユーザーID: 101
ユーザー名: Alice
更新後の名前: Alice (Updated)
まとめ
プロパティ(Property)は、C#におけるカプセル化の基本です。
{ get; set; }(自動実装プロパティ)は、クラスのデータを外部に公開する最も標準的な方法です。publicなフィールドを直接公開するのではなく、プロパティを使用することで、クラスのデータを安全に保護できます。{ get; private set; }を使用することで、外部からは変更不可能な「読み取り専用」のプロパティを簡単に定義できます。
