LoginSignup
21
9

More than 3 years have passed since last update.

C# 9.0 新機能 「init アクセサ (init 専用セッター)」

Last updated at Posted at 2021-03-25

今更ながらC#9.0から追加されたinitアクセサ(init 専用セッター)を使ってみたのでメモ
https://docs.microsoft.com/ja-jp/dotnet/csharp/whats-new/csharp-9#init-only-setters

前提

以下をメンバに持つSampleというクラスがあったとします。

  • getアクセサとsetアクセサを持つ通常のプロパティ(Property
  • getアクセサしか持たない get-only(read-only) なプロパティ(GetOnlyProperty
public class Sample
{
    public string Property { get; set; }    // get アクセサと set アクセサ
    public string GetOnlyProperty { get; }  // get アクセサのみ

    public Sample() { }

    public Sample(string property, string getOnlyProperty)
    {
        Property = property;
        GetOnlyProperty = getOnlyProperty;
    }
}

C# 8.0 まで

各プロパティに値を設定したい場合、以下のように
setアクセサを持つプロパティ(Property)はコンストラクタでもオブジェクト初期化子でも、それ以外でも値を設定することができます。

一方で、setアクセサを持たない get-only なプロパティ(GetOnlyProperty)は、コンストラクタでしか値を設定することができません。
もちろん、自クラスのメソッド(SampleMethod)内でも設定することはできません。

public class Sample
{
    public string Property { get; set; }
    public string GetOnlyProperty { get; }

    public Sample() { }

    public Sample(string property, string getOnlyProperty)
    {
        Property = property;
        GetOnlyProperty = getOnlyProperty;
    }

    public void SampleMethod(string property, string getOnlyProperty)
    {
        Property = property;                //OK
        GetOnlyProperty = getOnlyProperty;  //Error
    }
}

public class Program
{
    private static void Main(string[] args)
    {
        //コンストラクタで値を設定
        var s1 = new Sample("foo", "bar"); //OK

        //値を設定
        s1.Property = "baz";        //OK
        s1.GetOnlyProperty = "baz"; //Error

        //オブジェクト初期化子で値を設定
        var s2 = new Sample
        {
            Property = "foo",           //OK
            GetOnlyProperty = "bar",    //Error
        };
    }
}

コンストラクタでの初期化以降、値を書き換えられることが無い get-only なプロパティ(GetOnlyProperty)は、安全に利用することができますが、少々制限が厳しすぎると感じていた方もいらっしゃるのではないでしょうか。

具体的には、オブジェクト初期化子でも値を設定することができないという点です。

C# 8.0 までは 初期化処理(コンストラクタ及びオブジェクト初期化子)では値が設定できるが
それ以外は値を設定することができないプロパティを定義することはできません。

C# 9.0

C# 9.0 で導入されたinitアクセサ を利用すると、
上述した通り、C# 8.0 までは実現することができなかった
初期化処理(コンストラクタ及びオブジェクト初期化子)では値が設定できるが
それ以外は値を設定することができないプロパティを定義することができます。

get-onlyなプロパティに対してinit-onlyなプロパティと呼びます。

定義方法は非常に簡単で、setの代わりにinitと記述するだけです。

public string InitOnlyProperty { get; init; }

get-only なプロパティとの主な違いは
init-only プロパティでは、オブジェクト初期化子で値を設定することが出来るという点です。

もちろん get-only なプロパティ同様に、コンストラクタでも値を設定することができますし、
それ以外の場所では値を設定することができません。
(他のinitアクセサ内は除く)

initアクセサを利用することによって、 get-only なプロパティよりも柔軟に利用できるプロパティが定義できるようになりました。

public class Sample
{
    public string Property { get; set; }
    public string GetOnlyProperty { get; }
    public string InitOnlyProperty { get; init; }

    public Sample() { }

    public Sample(string property, string getOnlyProperty, string initOnlyProperty)
    {
        Property = property;                   //OK
        GetOnlyProperty = getOnlyProperty;     //OK
        InitOnlyProperty = initOnlyProperty;   //OK
    }

    public void SampleMethod(string property, string getOnlyProperty, string initOnlyProperty)
    {
        Property = property;                    //OK
        GetOnlyProperty = getOnlyProperty;      //Error
        InitOnlyProperty = initOnlyProperty;    //Error
    }
}

public class Program
{
    private static void Main(string[] args)
    {
        //コンストラクタで値を設定
        var s1 = new Sample("foo", "bar", "baz");

        //値を設定
        s1.Property = "qux";            //OK
        s1.GetOnlyProperty = "qux";     //Error
        s1.InitOnlyProperty = "qux";    //Error

        //オブジェクト初期化子で値を設定
        // get-only プロパティでは値を設定できないが、 init-only プロパティでは可能
        var s2 = new Sample
        {
            Property = "foo",           //OK
            GetOnlyProperty = "bar",    //Error
            InitOnlyProperty = "baz",       //OK
        };
    }
}

以上となります。

21
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
9