Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9509

C#9.0 レコード理解度テスト 《コンストラクタ編》

$
0
0
C#9.0 レコード理解度テスト 《コンストラクタ編》 C#9.0のレコードについて、 理解度を確認する問題を作ってみました。 今回のメインテーマはコンストラクタです。 初回なので、シンプルなコードを揃えています。 息抜きにぜひチャレンジしてください。 問題 次に12例のrecord定義を示します。 それぞれの例について、 「コンパイル可」「コンパイル不可」を答えてください。 「コンパイル不可」と答えた場合は、その理由を答えてください。 環境は以下の通りです Visual Studio 2019 C#9.0 .NET 5.0 null許容:有効化 基本編 問1 record MyRecord(string Name, int Number) { } 問2 record MyRecord() { public string? Name { get; init; } public int Number { get; init; } } 問3 record MyRecord { public string? Name { get; init; } public int Number { get; init; } } 引数なしコンストラクタ編 問4 record MyRecord(string Name, int Number) { public MyRecord() { Name = "Unknown"; Number = 0; } } 問5 record MyRecord() { public string Name { get; init; } public int Number { get; init; } public MyRecord() { Name = "Unknown"; Number = 0; } } 問6 record MyRecord { public string Name { get; init; } public int Number { get; init; } public MyRecord() { Name = "Unknown"; Number = 0; } } 引数ありコンストラクタ編 問7 record MyRecord(string Name, int Number) { public MyRecord(string name) { Name = name; } } 問8 record MyRecord() { public string Name { get; init; } public int Number { get; init; } public MyRecord(string name) { Name = name; } } 問9 record MyRecord { public string Name { get; init; } public int Number { get; init; } public MyRecord(string name) { Name = name; } } 本体書かない編 問10 record MyRecord(string Name, int Number); 問11 record MyRecord(); 問12 record MyRecord; 以上! 模範解答 今回のテーマはコンストラクタの違いでした。 考慮漏れがなかったかどうか確認していきましょう。 基本編 問1: コンパイル可 問2: コンパイル可 問3: コンパイル可 すべてコンパイルできます。 全く同じ定義というわけではなく、new するときに違いがあります。 問1 var r = new MyRecord("なまえ", 123); 問2,問3 var r = new MyRecord() { Name = "なまえ", Number = 123 }; 問2,問3、その2 var r = new MyRecord(); 問2、問3の例では、プロパティは初期化されないことがあります。 引数なしコンストラクタ編 問4: コンパイル不可 プライマリコンストラクタを呼び出していない。 問5: コンパイル不可 プライマリコンストラクタと定義が衝突している。 問6: コンパイル可 位置指定パラメータ が指定されているレコードでは、 プライマリコンストラクタ が生成されています。 コンストラクタは、基本的にプライマリコンストラクタを呼び出す必要があります。 また、問5では、本体に書いたコンストラクタはシグネチャが衝突してしまい、そもそも定義できません。 以下に、コンパイル可能な修正を示します。 問4修正版 thisを呼び出せばOK public MyRecord() : this("Unknown", 0) { } 引数ありコンストラクタ編 問7: コンパイル不可 プライマリコンストラクタを呼び出していない。 問8: コンパイル不可 プライマリコンストラクタを呼び出していない。 問9: コンパイル可 こちらも、プライマリコンストラクタの呼び出しがテーマになります。 以下に、コンパイル可能な修正を示します。 問7修正版 thisを呼び出せばOK public MyRecord(string name) : this(name, 0) { } 問8修正版 thisを呼び出せばOK public MyRecord(string name) : this() { Name = name; } 問9はコンパイル可ですが、引数なしのコンストラクタが無いことに注意して下さい。 問3、問6と同じ方法でのnewはコンパイル不可になります。 問9ではNG var r = new MyRecord() { Name = "なまえ", Number = 123 }; これならOK var r = new MyRecord("なまえ") { Number = 123 }; 問8修正版では、上記2つともnewできます。 本体書かない編 問10: コンパイル可 問11: コンパイル可 問12: コンパイル可 すべてコンパイル可能です。 問11、問12の例が役に立つかどうかはさておき、引数なしのコンストラクタはあるのでnewできます。 newはできる var r = new MyRecord(); おわりに 本当は『レコードには 位置指定パラメータ を使おう』というような記事を書こうと思っていました。 考えを整理するために色々試し始めたら、挙動の予想が出来ていない部分に気づき、これをまとめるための箸休め的な記事を書くことになりました。 少しでも皆さんの気づきの役に立っていれば幸いです。 次回はもう少し実のある記事を書きたい……

Viewing all articles
Browse latest Browse all 9509

Trending Articles