自動実装プロパティ
暗黙的なアクセッサ
実際の開発では、非公開のフィールドに対して、単に設定や取得を行うだけのプロパティが頻出します。つまり、以下のようなプロパティです。
private int x; public int X { get { return x; } set { x = value; } }
上のコードは private な x フィールドに対して、単に読み書きするだけの X プロパティを公開しています。
本来のアクセッサの役割を考えれば、入力された値を検証し、制約に基づいているかなどの制御を行うべきですが、それが必要ではないプロパティも少なくありません。または、ラフな設計段階であればとりあえず読み書きするだけのプロパティを用意し、仕様の詳細が定まった時点で後から検証コードなどを挟むということもあるでしょう。
このような、フィールドに対して単に読み書きするだけのプロパティであれば自動実装プロパティ(automatically implemented property)を利用すると便利です。自動実装プロパティは、アクセッサ本体にブロックを指定する代わりにセミコロン ; を記述します。
アクセッサ修飾子 get ;
アクセッサ修飾子 set ;
自動実装プロパティは get アクセッサと set アクセッサの両方でセミコロンを本体にしなければなりません。一方をブロックの本体にしたり、片方のアクセッサのみを指定するということはできません。必ず両方のアクセッサを記述し、セミコロンの本体を指定します。
pubic int X { get; set; }
上の X プロパティは自動実装プロパティです。プロパティの本体はブロックではなくセミコロンが指定されているため、コンパイル時に暗黙的な非公開フィールドと、それを読み書きするためのアクセッサが内部で生成されます。つまり、冒頭の X プロパティと同等のコードが生成されます。
class MagicalGirl { public string Name { get; set; } } class Test { public static void Main(string[] args) { MagicalGirl nanoha = new MagicalGirl(); nanoha.Name = "高町なのは"; System.Console.WriteLine("Name=" + nanoha.Name); } }
コード1の MagicalGirl クラスの Name プロパティは自動実装プロパティです。Main() メソッドで MagicalGirl クラスのオブジェクトを利用するコードでは、これまで通りの読み取り書き込み可能なプロパティでしかありません。プロパティを実装する手間がフィールドの宣言と大差なく、短いコードで簡単にプロパティを用意できます。
自動実装プロパティで get アクセッサまたは set アクセッサを省略した読み取り専用プロパティや書き込み専用プロパティを作成することはできません。ですが、一方のアクセッサだけを private で修飾することで、同じような効果を得られます。
class MagicalGirl { public string Name { get; private set; } public MagicalGirl(string name) { Name = name; } } class Test { public static void Main(string[] args) { MagicalGirl nanoha = new MagicalGirl("高町なのは"); nanoha.Name = "木之本桜"; //エラー System.Console.WriteLine("Name=" + nanoha.Name); } }
コード2の Name プロパティは public キーワードで修飾されていますが、set アクセッサが private キーワードで修飾されているため外部には公開されません。したがって、外部から見えるのは Name プロパティのうちの get アクセッサのみです。
Main() メソッド内でインスタンスを生成した後、Name プロパティに文字列を代入しようとしていますが set アクセッサが非公開になっているため、この操作は無効です。実行結果のように、コンパイルするとエラーが表示されます。外部のクラスから見たとき Name プロパティは読み取り専用プロパティのように機能します。