5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Posted at

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();

おわりに

本当は『レコードには 位置指定パラメータ を使おう』というような記事を書こうと思っていました。
考えを整理するために色々試し始めたら、挙動の予想が出来ていない部分に気づき、これをまとめるための箸休め的な記事を書くことになりました。

少しでも皆さんの気づきの役に立っていれば幸いです。

次回はもう少し実のある記事を書きたい……

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?