xin9le.net

Microsoft の製品/技術が大好きな Microsoft MVP な管理人の技術ブログです。

自動実装プロパティ初期化子

「Try! C# vNext」ということで、次期C#の新機能を少しずつ試していきたいと思います。まず最初は自動実装プロパティ初期化子 (= Auto-property initializers) です。これまではメンバー変数の初期化はクラス宣言と同時にできたのですが、自動実装プロパティはコンストラクタなどでしか初期化ができませんでした。その制約を取り払い、より簡潔な記述を可能にしようというものです。

とりあえず使ってみる

使い方は簡単で、以下のように自動実装プロパティに対して値を代入するように記述するだけです。

class Book
{
    public string Title{ get; set; } = "Untitled";
    public int Price{ get; set; } = 100;
}

これは以下の書き方と等価です。定型的な初期化するだけのコンストラクタがほぼほぼ不要になり、かなりスッキリとした記述になります。

class Book
{
    public string Title{ get; set; }
    public int Price{ get; set; }
    public Book()
    {
        this.Title = "Untitled";
        this.Price = 100;
    }
}

Getterのみの自動実装プロパティ (= Getter-only auto-properties)

自動実装プロパティの初期化ができるようになったことに伴い、Getterのみの自動実装プロパティも提供されるようになりました。

class Book
{
    public string Title{ get; } = "Untitled";  //--- そのまま初期化できる
    public int Price{ get; }
    public Book()
    {
        this.Price = 100;  //--- コンストラクタでも初期化できる
    }
}

自動実装プロパティは、内部的には「Backing Field」と呼ばれるプログラム上からは (リフレクションを利用しない限り) 触ることができない隠しフィールドを利用して値を保持しますが、これまでは値をどこからも設定できないGetterのみの自動実装プロパティはコンパイルエラーになっていました。この制約が解放された形になります。

Getterのみの自動実装プロパティを既存の方法で表現すると、だいたい以下のような形です。わざわざ変数を作る必要性がなくなるなど、コードが簡潔になることが分かります。

class Book
{
    public string Title{ get{ return this.title; } }
    private readonly string title = "Untitled";
}

コンパイル

今回Visual Studio 14 CTPに搭載されているC# vNextの新機能は、大半 (全部?) が糖衣構文 (= 既存構文を簡略化した別の書き方) です。新機能を動かすために.NET Frameworkの新しいバージョンが要求されるようなことはありません。ということでILSpyで生成された実行ファイルを逆コンパイルし、どのような展開がなされているかを確認してみましょう。

class Book
{
    public string Title{ get; set; } = "Untitled";
    public int Price{ get; } = 100;
}
class Book
{
    public string Title{ get; set; }
    public int Price
    {
        [CompilerGenerated]
        get{ return this.<Price>k__BackingField; }
    }
    public Book()
    {
        this.<Title>k__BackingField = "Untitled";
        this.<Price>k__BackingField = 100;
        base..ctor();
    }
}

ほぼほぼ分かっていたことですが、どちらもコンストラクタでBacking Fieldに対して値が挿入されていることが確認できます。