Encadenamiento de constructores en C#

Fil Zjazel Romaeus Villegas 12 octubre 2023
  1. ¿Qué es un constructor?
  2. ¿Qué es la sobrecarga de constructores?
  3. ¿Qué es el encadenamiento de constructores?
  4. Ejemplo de encadenamiento de constructores
Encadenamiento de constructores en C#

Este tutorial demostrará cómo hacer el encadenamiento de constructores en C#. Para comprender el encadenamiento de constructores, primero debe conocer los siguientes conceptos.

¿Qué es un constructor?

Un Constructor es un método en una clase que se ejecuta automáticamente cuando se crea un objeto. El constructor se puede dejar en blanco o también puede contener varias instrucciones y pasos que se seguirán cuando se cree una nueva instancia.

Considere esta clase de ejemplo a continuación. El constructor de esta clase establecerá automáticamente los valores de sus variables como se detalla a continuación en la inicialización. Si deja el constructor en blanco, todas las variables de clase serán null de forma predeterminada.

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;
  }
}

¿Qué es la sobrecarga de constructores?

La sobrecarga de constructores le permite llamar a un constructor diferente en función de los parámetros de entrada que proporcionó al crear una nueva instancia de la clase. Para cada escenario de parámetro aceptado, debe definir el constructor que se utilizará. Puede tener tantas sobrecargas de constructor como desee.

Hemos agregado otra función constructora que acepta una sola entrada de cadena en el ejemplo a continuación. Si se proporciona una entrada, establecerá la variable de nombre en el valor de entrada.

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;
  }
}

¿Qué es el encadenamiento de constructores?

El encadenamiento de constructores le permite llamar a otro constructor desde dentro de otro. Usando el mismo ejemplo, supongamos que crea una nueva instancia de Tutorial_Class sin pasar ningún parámetro. Podemos modificar el constructor inicial para tener un parámetro predeterminado que activará la llamada del segundo constructor. De ahí el nombre de encadenamiento de constructores. También puede pensar que es similar a los argumentos opcionales, que establecen un valor predeterminado independientemente de si ha pasado algo explícitamente.

En el siguiente ejemplo, en lugar de establecer los valores en el constructor inicial, pasamos el nombre predeterminado Tutorial Draft al constructor que activa el segundo constructor.

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;
  }
}

Ejemplo de encadenamiento de constructores

Usando los conceptos discutidos anteriormente, podemos aplicar el encadenamiento de constructores y ver cómo se comporta la clase dependiendo de las diferentes entradas.

Ejemplo:

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");
    }
  }
}

En el ejemplo anterior, creamos tres instancias de Tutorial_Class y proporcionamos diferentes parámetros para cada una. Puede observar que independientemente de qué constructor se inicializó primero, siempre activaron el tercer constructor, lo que se puede verificar al ver cómo las otras variables también tienen valores, no solo la descripción.

Otra cosa importante a tener en cuenta es que los constructores encadenados se llaman primero antes de ejecutar las instrucciones en su constructor principal. Esto se puede ver a través de la variable de descripción, que es diferente según los parámetros que se proporcionaron inicialmente.

Producción :

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