読者です 読者をやめる 読者になる 読者になる

Getterのみ自動実装プロパティの初期化子のメモ

うっかりやってしまいそうだなと思ったのでサンプルを残しておきます。

C# 6.0からの機能に

  • 自動実装プロパティの初期化子(Getterのみの自動実装プロパティ)
  • ラムダ式本体によるプロパティの記述

があります。

使う側からするとどちらも同じGetterプロパティですが、動きは微妙に違います。ちゃんと理解して使いわけたいと思います。

というより初期化するつもりでプロパティ内でメソッドを呼び出す場合は、うっかりラムダ式を書かないように。

class Sample {
    private static int GetValue([CallerMemberName]string caller = null) {
        // どのプロパティから呼ばれたか
        Console.WriteLine($"#{nameof(GetValue)} from {caller}");
        return 1;   // 値に意味なし
    }

    public Sample() {
        Console.WriteLine($"#{nameof(Sample)} Constructor");
    }

    // 自動実装プロパティの初期化子
    public int Value1 { get; } = GetValue();

    // ラムダ式本体によるプロパティ
    public int Value2 => GetValue();
}

class Program {
    static void Main(string[] args) {
        // Value1プロパティのGetValueメソッドは、
        // newしたタイミングでコンストラクタ本体より先に実行される
        Console.WriteLine($"new {nameof(Sample)}()");
        var sample = new Sample();
        // 結果:
        //new Sample()
        //#GetValue from Value1
        //#Sample Constructor

        // Value1プロパティを参照してもGetValueメソッドは実行されない
        Console.WriteLine($"{nameof(sample.Value1)}");
        var value1 = sample.Value1;
        // 結果:
        //Value1

        // Value2プロパティを参照するごとにGetValueメソッドが実行される
        Console.WriteLine($"{nameof(sample.Value2)}");
        var value2 = sample.Value2;
        // 結果:
        //Value2
        //#GetValue from Value2
    }
}