Start Debugging
2023-07-30 更新日 2023-11-05 csharp Edit on GitHub

C# 12 - プライマリコンストラクター

C# 12 から、クラスや構造体内でプライマリコンストラクターを定義できるようになりました。パラメーターは型名の直後の括弧に置かれます。これらのパラメーターは広いスコープを持ち、プロパティやフィールドの初期化、メソッドやローカル関数内の変数、ベースコンストラクターへの引き渡しに利用できます。

C# 12 から、クラスや構造体の中でプライマリコンストラクターを定義できるようになりました。パラメーターは型名の直後の括弧の中に配置します。

public class Car(string make)
{
    public string Make => make;
}

プライマリコンストラクターのパラメーターは広いスコープを持ちます。プロパティやフィールドの初期化、メソッドやローカル関数内の変数として、またベースコンストラクターへの引き渡しなどに利用できます。

プライマリコンストラクターを使うことは、これらのパラメーターがその型のあらゆるインスタンスにとって必須であることを意味します。明示的に書かれたコンストラクターが存在する場合、そのコンストラクターはプライマリコンストラクターを呼び出すために this(...) 初期化子構文を使用しなければなりません。これにより、すべてのコンストラクターが確実にプライマリコンストラクターのパラメーターへ値を割り当てます。

クラス、および record class 型を含むクラスでは、プライマリコンストラクターが存在する場合、暗黙のパラメーターなしコンストラクターは生成されません。一方、構造体、および record struct 型を含む構造体では、暗黙のパラメーターなしコンストラクターは常に生成され、プライマリコンストラクターのパラメーターを含むすべてのフィールドを 0 ビットパターンで初期化します。明示的なパラメーターなしコンストラクターを含めることにした場合、それはプライマリコンストラクターを呼び出さなければならず、それによってプライマリコンストラクターのパラメーターに別の値を提供できます。

次のコードはプライマリコンストラクターの例を示しています。

public class ElectricCar(string make, int batteryCapacity) : Car(make)
{
    public ElectricCar() : this("unknown", 0) 
    {
    }

    public int BatteryCapacity => batteryCapacity;
}

class 型と struct 型の中では、プライマリコンストラクターのパラメーターは型の本体全体でアクセス可能です。メンバーフィールドとして使用できます。利用される場合、コンパイラーはコンストラクターパラメーターを、コンパイラーが生成した名前の private フィールドへ自動的にキャプチャします。ただし、プライマリコンストラクターのパラメーターが型の本体のどこでも使われていない場合、private フィールドは生成されません。この予防的なルールは、プライマリコンストラクターのパラメーターがベースコンストラクターに渡される際に、誤って 2 つのコピーが割り当てられることを防ぎます。

型に record 修飾子が付けられている場合、コンパイラーは異なる方法を取り、プライマリコンストラクターのパラメーターと同じ名前の public プロパティを合成します。record class 型では、プライマリコンストラクターのパラメーター名がベースのプライマリコンストラクターと同じ場合、このプロパティはベースの record class 型の public プロパティとなり、派生 record class 型では重複して生成されません。これらのプロパティは record でない型には生成されない点に注意してください。

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< 戻る