Constructores de Instancias: Lenguaje C# (backend)

Los constructores de instancias se usan para crear e inicializar las variables miembro de instancia cuando se usa la expresión new para crear un objeto de una clase. Para inicializar una clase estática, o variables estáticas en una clase no estática, se define un constructor estático. Para obtener más información, vea Constructores estáticos (Guía de programación de C#).

En el siguiente ejemplo se muestra un constructor de instancias:

C#

class Coords
{
    public int x, y;

    // constructor
    public Coords()
    {
        x = 0;
        y = 0;
    }
}

 Nota

Para mayor claridad, esta clase contiene campos públicos. El uso de campos públicos no es una práctica de programación recomendada porque permite que cualquier método de cualquier parte de un programa obtenga acceso sin restricciones ni comprobaciones a los mecanismos internos de un objeto. Los miembros de datos generalmente deberían ser privados y solo se debería tener acceso a ellos a través de las propiedades y métodos de la clase.

Se llama a este constructor de instancias cada vez que se crea un objeto basado en la clase Coords. Un constructor como este, que no toma ningún argumento, se denomina constructor sin parámetros. Pero a menudo resulta útil proporcionar constructores adicionales. Por ejemplo, se puede agregar un constructor a la clase Coords que permita especificar los valores iniciales de los miembros de datos:

C#

// A constructor with two arguments.
public Coords(int x, int y)
{
    this.x = x;
    this.y = y;
}

Esto permite crear objetos Coords con valores iniciales predeterminados o específicos, como este:

C#

var p1 = new Coords();
var p2 = new Coords(5, 3);

Si una clase no tiene un constructor, se genera automáticamente un constructor sin parámetros y los valores predeterminados se usan para inicializar los campos del objeto. Por ejemplo, un int se inicializa en 0. Para obtener información sobre los valores predeterminados de los tipos, vea Valores predeterminados de los tipos de C#. Por tanto, dado que el constructor sin parámetros de la clase Coords inicializa todos los miembros de datos en cero, se puede quitar por completo sin cambiar el funcionamiento de la clase. Más adelante en este tema se proporciona un ejemplo completo del uso de varios constructores en el Ejemplo 1 y en el Ejemplo 2 se proporciona un ejemplo de un constructor generado automáticamente.

Los constructores de instancias también se pueden usar para llamar a los constructores de instancias de las clases base. El constructor de clase puede invocar el constructor de la clase base a través del inicializador, como sigue:

C#

class Circle : Shape
{
    public Circle(double radius)
        : base(radius, 0)
    {
    }
}

En este ejemplo, la clase Circle pasa valores que representan el radio y el alto al constructor proporcionado por Shape desde el que se deriva Circle. Un ejemplo completo del uso de Shape y Circle aparece en este tema en el Ejemplo 3.

Ejemplo 1

En el ejemplo siguiente se muestra una clase con dos constructores de clase, uno sin argumentos y uno con dos argumentos.

C#

class Coords
{
    public int x, y;

    // Default constructor.
    public Coords()
    {
        x = 0;
        y = 0;
    }

    // A constructor with two arguments.
    public Coords(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    // Override the ToString method.
    public override string ToString()
    {
        return $"({x},{y})";
    }
}

class MainClass
{
    static void Main()
    {
        var p1 = new Coords();
        var p2 = new Coords(5, 3);

        // Display the results using the overriden ToString method.
        Console.WriteLine($"Coords #1 at {p1}");
        Console.WriteLine($"Coords #2 at {p2}");
        Console.ReadKey();
    }
}
/* Output:
 Coords #1 at (0,0)
 Coords #2 at (5,3)
*/

Ejemplo 2

En este ejemplo, la clase Person no tiene ningún constructor, en cuyo caso, se proporciona automáticamente un constructor sin parámetros y los campos se inicializan en sus valores predeterminados.

C#

using System;

public class Person
{
    public int age;
    public string name;
}

class TestPerson
{
    static void Main()
    {
        var person = new Person();

        Console.WriteLine($"Name: {person.name}, Age: {person.age}");
        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
// Output:  Name: , Age: 0

Observe que el valor predeterminado de age es 0 y el valor predeterminado de name es null.

Ejemplo 3

En el ejemplo siguiente se muestra cómo usar el inicializador de la clase base. La clase Circle se deriva de la clase general Shape y la clase Cylinder se deriva de la clase Circle. En cada clase derivada, el constructor usa su inicializador de clase base.

C#

using System;

abstract class Shape
{
    public const double pi = Math.PI;
    protected double x, y;

    public Shape(double x, double y)
    {
        this.x = x;
        this.y = y;
    }

    public abstract double Area();
}

class Circle : Shape
{
    public Circle(double radius)
        : base(radius, 0)
    {
    }

    public override double Area()
    {
        return pi * x * x;
    }
}

class Cylinder : Circle
{
    public Cylinder(double radius, double height)
        : base(radius)
    {
        y = height;
    }

    public override double Area()
    {
        return (2 * base.Area()) + (2 * pi * x * y);
    }
}

class TestShapes
{
    static void Main()
    {
        double radius = 2.5;
        double height = 3.0;

        Circle ring = new Circle(radius);
        Cylinder tube = new Cylinder(radius, height);

        Console.WriteLine("Area of the circle = {0:F2}", ring.Area());
        Console.WriteLine("Area of the cylinder = {0:F2}", tube.Area());

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
    Area of the circle = 19.63
    Area of the cylinder = 86.39
*/

Para obtener más ejemplos sobre cómo invocar los constructores de clase base, vea virtualoverride y base.