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 的新例項。我們可以修改初始建構函式,使其具有一個預設引數,該引數將觸發第二個建構函式被呼叫。因此得名建構函式鏈。你也可以將其視為類似於可選引數,無論你是否顯式傳遞任何內容,它都會設定預設值。

在下面的示例中,我們沒有在初始建構函式中設定值,而是將預設名稱 Tutorial Draft 傳遞給觸發第二個建構函式的建構函式。

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 的三個例項,併為每個例項提供了不同的引數。你可以觀察到,無論哪個建構函式先初始化,它們總是觸發第三個建構函式,這可以通過檢視其他變數如何具有值來驗證,而不僅僅是描述。

另一個需要注意的重要事情是,在執行其主建構函式中的指令之前,首先呼叫鏈式建構函式。這可以通過描述變數看到,該變數根據最初提供的引數而有所不同。

輸出:

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