ホームに戻る
出典 :
関連 :
目次 :
※ プロパティを併せて参照のこと。
オブジェクト初期化子
オブジェクトが書き換え可能なフィールドまたはプロパティを有している場合、オブジェクトの作成時に初期値をまとめて割り当てることができる。
public class Cat
{
// 書き換え可能プロパティ( set アクセサあり)
public int Age { get; set; }
public string? Name { get; set; }
// コンストラクタ
public Cat()
{
}
// コンストラクタ
public Cat(string name)
{
this.Name = name;
}
}
:
{
// オブジェクト初期化子を用いて Age と Name を初期化
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
// オブジェクト初期化子を用いて Age を初期化
// ( Name はコンストラクタ引数として指定)
Cat sameCat = new Cat("Fluffy") { Age = 10 };
}
上記ではオブジェクト初期化子を用いて、Cat 型オブジェクトの各プロパティに初期値を与えている。
このようにプロパティ(またはフィールド)が書き換え可能であれば、コンストラクタに初期化文を記述する必要が無い。
但し、プロパティが読み取り専用の場合は同様の手法を用いることができない(後述)。
読み取り専用プロパティの実装
C# 8.0までは、以下の要領で読み取り専用データを実装していた。
- フィールドを readonly で宣言する
- プロパティに get アクセサのみを定義する( set を定義しない)
struct Point
{
// 読み取り専用フィールド
public readonly string name;
// 読み取り専用プロパティ
public int X { get; }
public int Y { get; }
// コンストラクタ
public Point(string name, int x, int y)
{
// 読み取り専用フィールドの初期化
this.name = name;
// 読み取り専用プロパティの初期化
this.X = x;
this.Y = y;
}
}
:
{
// Point 型オブジェクト point の生成
var point = new Point("Point A", 1, 2);
// 以下のコードはエラーとなる
// (読み取り専用データを更新しようとしている)
// point.name = "new name";
// point.X = 3;
}
コンストラクタで初期値を受け取ってフィールドやプロパティに代入するボイラープレート的なコードが毎回必要であるため、
煩雑であるとともに、コンストラクタ実装やデータ初期化の自由度が低い。
init アクセサ
前節の問題を解決するため、C# 9.0では init アクセサが追加された。
これは set とは異なり、プロパティの初期化時にのみ使用される。
public class Cat
{
// init アクセサを定義したプロパティ
public int Age { get; init; }
public string? Name { get; init; }
// コンストラクタ
public Cat()
{
}
// コンストラクタ
public Cat(string name)
{
this.Name = name;
}
}
:
{
// オブジェクト初期化子を用いて Age と Name を初期化
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
// オブジェクト初期化子を用いて Age を初期化
// ( Name はコンストラクタ引数として指定)
Cat sameCat = new Cat("Fluffy") { Age = 10 };
// 以下のコードはエラーとなる
// ( set が定義されていないため)
// cat.Name = "other name"
}
init が定義されている場合、( set と同様に)オブジェクト初期化子を用いた初期値の割り当てが可能である。
これにより、読み取り専用プロパティでもオブジェクト初期化子を用いた初期化が可能で、簡便に記述ができる。