3
1

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 1 year has passed since last update.

C# 11 で初期化子を使った完全コンストラクターパターンを書いてみるんだ

Posted at

どうも、完全コンストラクターパターン大好きマンです。でも、コンストラクターをいちいち書くのは面倒くさい。
インテリコードさんがある程度自動で書いてくれるものの、パラメーター追加時に XML コメントの追加を忘れたり・・・できることならデフォルトコンストラクターで済ませたいです。

初期化子の中で代入すればいいじゃないか、となりますが、初期化し忘れが怖い。
そこを解決してくれる機能が C# 11 で追加されました!

C# 11 で追加された required キーワード と C# 9 ですでに追加されている init キーワード を使って、長ったらしいコンストラクターを書かずに完全コンストラクターパターンを実現してみましょう!

①今までの書き方

internal sealed class UserOld
{
    internal string Name { get; }

    internal string Email { get; }

    internal int Age { get; }

    public UserOld(string name, string email, int age)
    {
        Name = name;
        Email = email;
        Age = age;
    }
}
  1. プロパティは get のみ定義
  2. コンストラクターですべてのプロパティを初期化

このようにシンプルなクラスだったら気にならないけど、プロパティが増えたり名前が複雑になってくると面倒ですよね。
このクラスを使ってみると・・・

UserOld old1 = new("ひげげ", "higege@higege.com", 45);
UserOld old2 = new("ひげげ", "higege@higege.com"); // CS7036 エラー

image.png
初期化し忘れを排除できます。

②required を使って書いてみる

internal sealed class User
{
    internal required string Name { get; init; }

    internal required string Email { get; init; }

    internal required int Age { get; init; }

    public User()
    {
    }
}
  1. すべてのプロパティに required キーワードをつける
  2. すべてのプロパティに get init を定義する
  3. デフォルトコンストラクターでOK(書かなくても問題ない)

見慣れない required がありますが、すっきりしています。
このクラスを使ってみると・・・

User user1 = new()
{
    Name = "ひげげ",
    Email = "higege@higege.com",
    Age = 45,
};

User user2 = new()
{
    Name = "ひげげ",
    Email = "higege@higege.com",
}; // CS9035 エラー

image.png
同様に、初期化し忘れを排除できました。

比べてみる

クラスの実装

行数少なくキーワードで属性の説明がされている②が若干わかりやすいか。かといって①がわかりにくいかと言ったらNO。

使用箇所

比較のため①も改行して並べてみます。

UserOld old1 = new(
    "ひげげ",
    "higege@higege.com",
    45);

User user1 = new()
{
    Name = "ひげげ",
    Email = "higege@higege.com",
    Age = 45,
};

いや、やはり使用箇所は断然①でしょう。クラス実装時の面倒よりも、使用箇所の面倒の方がイヤ。

その他の課題

プロパティのルールはどう実装するんだ?①だったらコンストラクターないで順番にチェック、②は init を実装か。
そうするとクラスの実装のシンプルさが損なわれてしまう・・・うーん。

まとめ

使用箇所の実装量・可読性から、これからも長ったらしいコンストラクターを書いていこうと思います。(チャンチャン

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?