C# でのコンストラクターチェーン

Fil Zjazel Romaeus Villegas 2023年10月12日
  1. コンストラクターとは何ですか
  2. コンストラクターのオーバーロードとは何ですか
  3. コンストラクターチェーンとは何ですか
  4. コンストラクター連鎖の例
C# でのコンストラクターチェーン

このチュートリアルでは、C# でコンストラクターチェーンを実行する方法を示します。コンストラクターチェーンを理解するには、最初に次の概念を知っている必要があります。

コンストラクターとは何ですか

コンストラクターは、オブジェクトの作成時に自動的に実行されるクラス内のメソッドです。コンストラクターは空白のままにすることも、新しいインスタンスが作成されるときに実行されるさまざまな命令や手順を含めることもできます。

以下のこのサンプルクラスについて考えてみます。このクラスのコンストラクターは、初期化時に以下に詳述するように、その変数の値を自動的に設定します。コンストラクターを空白のままにすると、デフォルトですべてのクラス変数が代わりに null になります。

class Tutorial_Class {
  public string name;
  public DateTime created_date;
  public List<string> topics;
  public string description;
  public bool draft;

  public Tutorial_Class() {
    // This is the constructor method
    this.name = "Tutorial Draft";
    this.created_date = DateTime.Now;
    this.topics = new List<string>();
    this.description = "Tutorial Description";
    this.draft = false;
  }
}

コンストラクターのオーバーロードとは何ですか

コンストラクターのオーバーロードを使用すると、クラスの新しいインスタンスを作成するときに指定した入力パラメーターに基づいて、別のコンストラクターを呼び出すことができます。受け入れられたパラメーターシナリオごとに、使用するコンストラクターを定義する必要があります。コンストラクターのオーバーロードは、必要な数だけ持つことができます。

以下の例では、単一の文字列入力を受け入れる別のコンストラクター関数を追加しました。入力が提供されると、name 変数が入力値の名前変数に設定されます。

class Tutorial_Class {
  public string name;
  public DateTime created_date;
  public List<string> topics;
  public string description;
  public bool draft;

  public Tutorial_Class() {
    // This is the initial constructor method and will be used if no parameter is passed
    this.name = "Tutorial Draft";
    this.created_date = DateTime.Now;
    this.topics = new List<string>();
    this.description = "Tutorial Description";
    this.draft = false;
  }

  public Tutorial_Class(string name) {
    // This is the second constructor method and will be used if you pass a single string parameter
    // Instead of the name variable being set to "Tutorial Draft", it will be set to the value of
    // the input parameter
    this.name = name;
    this.created_date = DateTime.Now;
    this.topics = new List<string>();
    this.description = "Tutorial Description";
    this.draft = false;
  }
}

コンストラクターチェーンとは何ですか

コンストラクターチェーンを使用すると、別のコンストラクター内から別のコンストラクターを呼び出すことができます。同じ例を使用して、パラメータを渡さずに Tutorial_Class の新しいインスタンスを作成するとします。最初のコンストラクターを変更して、2 番目のコンストラクターが呼び出されるようにトリガーするデフォルトのパラメーターを設定できます。したがって、名前はコンストラクタチェーンです。また、明示的に何かを渡したかどうかに関係なくデフォルト値を設定するオプションの引数に似ていると考えることもできます。

以下の例では、最初のコンストラクターで値を設定する代わりに、デフォルト名 Tutorial Draft をコンストラクターに渡し、2 番目のコンストラクターをトリガーします。

class Tutorial_Class {
  public string name;
  public DateTime created_date;
  public List<string> topics;
  public string description;
  public bool draft;

  public Tutorial_Class() : this("Tutorial Draft") {
    // The intiial constructor is now blank but will trigger the second constructor due to the
    // "this("Tutorial Draft")" line.
    // If you remove the parameter, all of the class variables will again be null by default instead
  }

  public Tutorial_Class(string name) {
    // As the initial constructor passed a single string parameter, this constructor is then called
    // and all variable values are set
    this.name = name;
    this.created_date = DateTime.Now;
    this.topics = new List<string>();
    this.description = "Tutorial Description";
    this.draft = false;
  }
}

コンストラクター連鎖の例

上記の概念を使用して、コンストラクターチェーンを適用し、さまざまな入力に応じてクラスがどのように動作するかを確認できます。

例:

using System;
using System.Collections.Generic;

namespace ConstructorChaining_Example {
  class Program {
    static void Main(string[] args) {
      // Initialize a new instance of the class with no parameters
      Tutorial_Class no_params = new Tutorial_Class();
      // Print the results to the console
      Console.WriteLine("Tutorial_Class with No Parameters:\n");
      PrintVariables(no_params);

      // Initialize a new instance of the class with the tutorial name "Sample Tutorial 1"
      Tutorial_Class string_param = new Tutorial_Class("Sample Tutorial 1");
      // Print the results to the console
      Console.WriteLine("Tutorial_Class with a Tutorial Name Provided:\n");
      PrintVariables(string_param);

      // Initialize a new instance of the class with the tutorial name "Sample Tutorial 2" and a
      // created date of December 31, 2021.
      Tutorial_Class string_and_date_param =
          new Tutorial_Class("Sample Tutorial 2", new DateTime(2021, 12, 31));
      // Print the results to the console
      Console.WriteLine("Tutorial_Class with a Tutorial Name and Created Date Provided:\n");
      PrintVariables(string_and_date_param);

      Console.ReadLine();
    }

    public class Tutorial_Class {
      public string name;
      public DateTime created_date;
      public List<string> topics;
      public string description;
      public bool draft;

      public Tutorial_Class() : this("Tutorial Draft") {
        // This is the initial constructor class which is only executed when no parameters are
        // passed Once the class is created, the second constructor class will be triggered with the
        // name parameter "Tutorial Draft"
        this.description = "No Parameter Passed";
      }

      public Tutorial_Class(string name) : this(name, DateTime.Now) {
        // This is the second constructor class
        // This can be called by two ways, either by initializing the class with no parameters or by
        // passing a specific string parameter for the tutorial name Regardless of how this
        // constructor is triggered, it will by default also execute the third constructor class by
        // passing the current DateTime as the date param
        this.description = "A tutorial name has been passed";
      }

      public Tutorial_Class(string name, DateTime date) {
        // This is the third constructor class
        // Regardless of how the class is initialized, this will always be triggered due to how the
        // constructors are chained
        this.name = name;
        this.created_date = date;
        this.topics = new List<string>();
        this.description = "A tutorial name and created date have both been passed";
        this.draft = false;
      }
    }

    public static void PrintVariables(Tutorial_Class tutorial) {
      // This function accepts a Tutorial_Class and prints three of its variables to the console
      Console.WriteLine("Tutorial Name: " + tutorial.name + "\n");
      Console.WriteLine("Created Date: " + tutorial.created_date.ToString() + "\n");
      Console.WriteLine("Description: " + tutorial.description + "\n");

      Console.WriteLine("\n");
    }
  }
}

上記の例では、Tutorial_Class の 3つのインスタンスを作成し、それぞれに異なるパラメーターを提供しました。最初に初期化されたコンストラクターに関係なく、常に 3 番目のコンストラクターがトリガーされていることがわかります。これは、説明だけでなく、他の変数にも値があることを確認することで確認できます。

注意すべきもう 1つの重要な点は、メインコンストラクターで命令を実行する前に、チェーンコンストラクターが最初に呼び出されることです。これは、最初に提供されたパラメーターによって異なる description 変数で確認できます。

出力:

Tutorial_Class with No Parameters:

Tutorial Name: Tutorial Draft

Created Date: 28/12/2021 8:25:35 pm

Description: No Parameter Passed



Tutorial_Class with a Tutorial Name Provided:

Tutorial Name: Sample Tutorial 1

Created Date: 28/12/2021 8:25:35 pm

Description: A tutorial name has been passed



Tutorial_Class with a Tutorial Name and Created Date Provided:

Tutorial Name: Sample Tutorial 2

Created Date: 31/12/2021 12:00:00 am

Description: A tutorial name and created date have both been passed