レコード内のプロパティを2回定義する
C#9では、プライマリコンストラクターと本体の両方のレコードに同じ名前のプロパティを定義できます。
record Cat(int PawCount)
{
public int PawCount { get; init; }
}
このコードはエラーなしでコンパイルされます。
このようなレコードのインスタンスを初期化する場合、コンストラクターに提供される値は完全に無視されます。
Console.WriteLine(new Cat(4));
Console.WriteLine(new Cat(4) { PawCount = 1 });
プリント
Cat { PawCount = 0 }
Cat { PawCount = 1 }
この動作は正しいですか、それともバグですか?それが正しければ、それが役立つ場合は何ですか?
いずれかのようなエラーで、このコードを拒否するように、私は、コンパイラを期待「タイプは、Cat
すでにの定義が含まれているPawCount
」またはコンストラクタから初期化を実行し、同じコンストラクタで、体内でプロパティを検討してください。後者のバリアントは、本体の位置レコードのすべてのプロパティを書き直すことなく、カスタムゲッターやイニシャライザーをプロパティに提供するのに役立ちます。
実際の動作は私には意味がありません。
回答
これを行う正しい方法は次のとおりです。
record Cat(int PawCount)
{
public int PawCount { get; init; } = PawCount;
}
これにより、検証などを実行できるので便利です。
record Cat(int PawCount)
{
private int _pawCount;
public int PawCount {
get => _pawCount;
init => _pawCount = value < 0 ? throw new ArgumentException() : value;
} = PawCount;
}
これの仕様はここにあります: https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/records.md#members-of-a-record-type
「一致する」署名を持つメンバーがレコード本体で宣言されていない限り、または「一致する」署名を持つアクセス可能な具象非仮想メンバーが継承されない限り、メンバーは合成されます。2つのメンバーが同じ署名を持っているか、継承シナリオで「隠れている」と見なされる場合、2つのメンバーは一致していると見なされます。
したがって、パラメーターと同じ名前のプロパティが既に存在するため、コンパイラーはPawCount
プロパティを合成せず、明示的に使用しない限り、パラメーターを黙って無視します。