blogで雑にまとめたC# 9.0から使えるinit アクセサーについて、
ちゃんと検証したので記事にした
公式ドキュメント
公式は正義
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/properties
C#8.0 以前では model 定義の際には
public class HogeClass
{
public string hoge { get; set; }
}
のように、値取得のためのgetアクセサーと値を格納するためのsetアクセサーを使用できた
ただし、setをつけると後から値が変更されてしまい、具合がよくないことがあるので
読み込み専用の model として
public class GetOnlyClass
{
public string? property { get; }
public GetOnlyClass()
{
}
public GetOnlyClass(string property)
{
this.property = property;
}
}
// get の場合はコンストラクタで値を設定する
var getOnlyClass = new GetOnlyClass("hoge");
Console.WriteLine(getOnlyClass.property);
// getOnlyClass.property = "fuga"; // NG 値の更新はできない
と、書いていた
ちなみに、set アクセサーがないとオブジェクト初期化子も使用できないので、
var getOnlyClass = new GetOnlyClass { property = "hoge" }; // NG
もできないといった制約があった
↓のように、読み取り専用だよって言われる
init アクセサーについて
C# 9.0 からはオブジェクト初期化子のみで値の設定ができる、initが使用できるとのこと
書き方は簡単で、set アクセサーの変わりにinit を使用するだけでよい
public class InitClass
{
public string? property { get; init; }
}
// オブジェクト初期化子で値の設定ができる
var initClass = new InitClass { property = "hoge"};
ちなみに、↑の状態でコンストラクタ内で値を設定しようとすると
怒られる
ので、コンストラクタを書けば、コンストラクタでの値の設定をすることができる
public class InitCconstructorClass
{
public string? property { get; init; }
// 引数なしのコンストラクタを定義する
public InitCconstructorClass()
{
}
public InitCconstructorClass(string property)
{
this.property = property;
}
}
この書き方なら、コンストラクタと初期化時両方で値の設定ができる(かつ、後で変更ができない)
ので、get onlyよりも使い勝手がよい