クラスメンバーのひとつのプロパティ(property)についてです。
プロパティはクラス内部のデータを外部とやり取りするためにC#が用意した機能です。
プロパティを使い、クラスのプライベートフィールドの値の取得や変更するために使います。
なんのためにこんなプロパティがあるのかというと、クラスの外部(呼び出す側)に対して必要最低限の情報を公開することで、修正時にクラス内部の変更だけで済むようしたり、外部からの誤操作でデータが書き換えられてしまうことを防ぐことを目的にしています。
プロパティの定義
プロパティの定義はこんな感じです。
プロパティにはデータを取得するためのgetアクセサー(accessor)とデータを設定するためのsetアクセサーがあります。
アクセスレベル 戻り値の型 プロパティ名 {
アクセスレベル get
{
// getアクセサー
// 外部からプロパティを取得しようとしたときに呼ばれる
// { } ブロック内でreturnを使い値を返す
}
アクセスレベル set
{
// setアクセサー
// 外部からプロパティに値が渡されたときに呼ばれる
// 外部から渡された値は変数valueに設定されている
}
}
アクセスレベルにはprivate、publicなどを指定します。
プロパティ本体、getアクセサー、setアクセサーそれぞれにアクセスレベルを指定することが出来ます。getは外部に公開して、setは内部だけという使い方が出来ます。
プロパティ本体のアクセスレベルを省略した場合はprivate、
get、setのアクセスレベルを省略した場合はpublicになるみたいです。
戻り値の型はデータ型を指定します。これがgetアクセサーの戻り値の型、setアクセサーに渡される変数valueの型になります。
getアクセサーは外部からプロパティを取得しようとしたときに呼ばれるメソッドです。returnを使い値を返します。{ }ブロック内からクラスメンバーにアクセスことが出来ます。
setアクセサーは外部からプロパティに値が設定されたときに呼ばれるメソッドです。
外部から与えられた値がvalueという変数に格納されています。
同じ名前のフィールドがクラス内にある場合は、thisを使いクラスメンバー(this.value)と変数valueを区別します。こちらも{ } ブロック内からクラスメンバーにアクセスすることが出来ます。
get、set両方のアクセサーを持つプロパティは読み取り/書き込み
getアクセサーのみを持つプロパティは読み取り専用、
setアクセサーのみを持つプロパティは書き込み専用になります。
サンプルコードです。
using System;
class Program
{
public static void Main()
{
var cls = new Sample();
// プロパティに値を設定(setアクセサーが呼ばれる)
cls.prop1 = 10;
// プロパティの値を取得(getアクセサーが呼ばれる)
Console.WriteLine(cls.prop1);
}
}
class Sample
{
// プライベートフィールド
private int privateData;
// プロパティ
public int prop1 {
// getアクセサー(プライベートフィールドを返す)
get { return this.privateData; }
// setアクセサー(プライベートフィールドに値を設定)
set { this.privateData = value; }
}
}
クラス内でプロパティの値を保存している変数(サンプルだと変数privateData)をバッキングフィールド(backing field)と言います。
get、setアクセサーのブロック内が1つの式だけの場合、=> を使い { } を省略することが出来ます。
class Sample
{
// プライベートフィールド
private int privateData;
// プロパティ
public int prop1
{
// getアクセサー(プライベートフィールドを返す)
get => this.privateData;
// setアクセサー(プライベートフィールドに値を設定)
set => this.privateData = value;
}
}
自動実装プロパティ
get、setアクセサーの処理の記述は省略することができます。
省略した場合は、プロパティとその値を保存するバッキングフィールドが自動で作成されます。これを自動実装プロパティといいます。
プロパティ名とプロパティの値を保存するバッキングフィールド名が同じ名前になります。下のサンプルで言うと、外部からのプロパティへのアクセスも内部からのフィールドへのアクセスもprop1という名前を使うということです。
getアクセサーだけのプロパティも自動実装プロパティが使えます。
setアクセサーだけのプロパティはダメ。
using System;
class Program
{
public static void Main()
{
var cls = new Sample();
// プロパティに値を設定(setアクセサーが呼ばれる)
cls.prop1 = 10;
// プロパティの値を取得(getアクセサーが呼ばれる)
Console.WriteLine(cls.prop1);
}
}
class Sample
{
// 読み込み/書き込みが出来るプロパティ
public int prop1 { get; set; }
// 読み込み専用プロパティ(値の設定はクラス内部で行う)
public int prop2 { get; }
public void method()
{
// バッキングフィールドにアクセス
Console.WriteLine(this.prop1);
}
}
コメント