こんにちは、サイオステクノロジー武井です。今回は、C#のプロパティについて説明したいと思います。
メンバー変数へのアクセス
オブジェクト指向では、一般的にメンバー変数へのアクセスは、直接行われません。誰でも自由に書き換えられたら困るからです。なので、getter、setterメソッドを通して、行われるのが一般的です。Javaなんかだと、メジャーですよね。
getter、setterメソッドを使う場合
まずプロパティを使わない場合、つまりgetter、setterメソッドを使う場合は以下のようなコードになります。
class Program { static void Main(string[] args) { Product hoge = new Product(); hoge.SetName("ほげ"); hoge.SetPrice(1000); Console.WriteLine("商品名は" + hoge.GetName() + "で、価格は" + hoge.GetPrice() + "円だよ") ; } } class Product { private string name; private int price; public string GetName() { return this.name; } public void SetName(string name) { this.name = name; } public int GetPrice() { return this.price; } public void SetPrice(int price) { if (price > 0) throw new ArgumentException(); this.price = price; } }
Productというクラスがあり、2つのメンバー変数name(商品名)、price(価格)があります。そのメンバー変数にアクセスするためのメソッドとして、GetName、SetName、GetPrice、SetPriceがあります。商品名にほげ、価格に1000をセットして結果を表示しています。
プロパティを使う場合
プロパティは、クラスその外から見るとメンバー変数のように振る舞い、クラスの内部から見るとメソッドのように振る舞います。プロパティを使う場合は以下のようなコードになります。
class Program { static void Main(string[] args) { Product hoge = new Product(); // このようにNameやPriceに代入するとsetが呼ばれます。 hoge.Name = "ほげ"; hoge.Price = 1000; // このようにNameやPriceにアクセスすると、getが呼ばれます。 Console.WriteLine("商品名は" + hoge.Name + "で、価格は" + hoge.Price + "円だよ"); } } class Product { private string name; private int price; // setter、getterの代わりに以下のように定義します。 // クラスの外部から[インスタンス名].Nameとアクセスしたときにgetが呼ばれて、 // [インスタンス名].Name = ...のように何かを代入すると、setが呼ばれます。 public string Name { get { return name; } set { name = value; } } public int Price { get { return price; } set { if (value > 0) throw new ArgumentException(); price = value; } } }
最初にご紹介した、Productクラスを利用する側からgetter、setterメソッドを使う場合より、記述がスッキリしたような気がしませんか?Productクラスを利用する側から、メンバー変数に何かを代入するときに、わざわざメソッド経由というのは、直感的ではなく、コードもなんかグチャッとします。とは言うもののクラスを作成する側からすれば、直接メンバー変数への代入は避けたいところです。どんな値でも自由に入れられるのはバグの温床にもなります。ProductのPriceみたいに0円未満は例外としたいときもあります。そこでプロパティなのです。
改めて見比べてみますと、setterメソッドを使って変数に代入する場合は、
hoge.SetPrice(1000);
となりますが、プロパティの場合は
hoge.Price = 1000;
となります。プロパティ使ったほうが直感的でスッキリしていますよね。当然、このときsetも呼ばれますので、0円未満は例外となります。
自動プロパティ
C#の自動プロパティを使うと、さらに以下のように記述を省略することが出来ます。
class Program { static void Main(string[] args) { Product hoge = new Product(); hoge.Name = "ほげ"; hoge.Price = 1000; Console.WriteLine("商品名は" + hoge.Name + "で、価格は" + hoge.Price + "円だよ"); } } class Product { private int price; public string Name { get; set; } public int Price { get { return price; } set { if (value > 0) throw new ArgumentException(); price = value; } } }
以下の記述を削除して、
private string name;
Nameのget、setの部分を以下のように変更しました。
public string Name { get; set; }
より記載がシンプルになりました。
get-onlyプロパティ
getだけのプロパティも定義できます。この場合、Productクラスの利用者はsetは使えません。コンストラクタだけで値を代入して、それ以外の代入方法を潰したいときに便利です。
class Program { static void Main(string[] args) { Product hoge = new Product("ほげ",1000); // hoge.Name = "ほげ"; ← この記述はコンパイルエラーになります。 Console.WriteLine("商品名は" + hoge.Name + "で、価格は" + hoge.Price + "円だよ"); } } class Product { public Product(string name,int price) { if (price > 0) throw new ArgumentException(); Name = name; Price = price; } public string Name { get; } public int Price { get; } }