Constructores, inicializacion rapida de objetos y C# 3.0

La inicialización rápida de objetos es una nueva e interesante característica de C# 3.0, pero me gustaria reflexionar un poco sobre su uso y el de nuestros amigos los constructores.

Un constructor es el método de una instancia que implementa las acciones necesarias para inicializar la instancia de la clase, y es invocado por el operador new cuando instanciamos dicha clase.  Por lo tanto, cuando desarrollamos una clase, el ó los constructores deben de tener la capacidad de inicializar los aspectos básicos de funcionamiento del objeto.

En C#, cuando no implementamos ningún constructor, el compilador asume que tenemos un constructor sin parámetros, es decir, esto:

[more]

class MyClass
{
    public String Field1 { get; private set; }
    public String Field2 { get; private set; }
}

es lo mismo que esto:

class MyClass
{
    public String Field1 { get; private set; }
    public String Field2 { get; private set; }
 
    public MyClass()
    {
    }
}

En el momento que definamos un constructor con parámetros, el compilador deja de asumir la existencia del constructor sin ellos, el motivo me parece más que obvio, si definimos un constructor con parámetros estamos diciendo que nuestra clase necesita “otras cosas” para poder inicializarse correctamente; si queremos tener otro sin parámetros tendremos que definirlo explicitamente.

Una ve las ventajas de usar un constructor paramétrizado, es por ejemplo inicializar propiedades públicas con setter privado, y modificarlas desde el constructor en base a los parámetros (seguro que no lo has hecho nunca xD); pero la principal ventaja es que le dice al programador que se necesita para ser inicializado y poder empezar a trabajar. A veces no necesitamos parámetros y otras veces es inevitable y debemos definir un constructor sin parámetros, como por ejemplo para permitir la serialización en Xml.

Definir constructores es bastante llevadero y poco pesado, ya que gracias a la sobrecarga, se escriben rápido, sin repetir el código en cada uno de ellos y queda bastante claro:

class MyControl : Control
{
    public String Field1 { get; private set; }
    public String Field2 { get; private set; }
    public String Field3 { get; private set; }
 
    // base: nos permite pasar parámetros a la 
    // clase de la que heredamos
    public MyControl(Control parent, String text, String field1)
        : base(parent, text)
    {
        this.Field1 = field1;
    }
 
    // this: nos permite invocar a otro constructor
    // de la misma clase, de forma que lo que escribimos
    // en este prosigue la labor del otro, evitandonos escribir
    // otra vez lo mismo para cada constructor.
    public MyControl(Control parent, String text, String field1, String field2)
        : this(parent, text, field1)
    {
        this.Field2 = field2;
    }
 
    // this: nos permite llamar a cualquier constructor
    // de la misma clase.
    public MyControl(Control parent, String text, String field1, String field2, String field3)
        : this(parent, text, field1,field2)
    {
        this.Field3 = field3;
    }
}

También se pueden definir modificadores de acceso en los constructores, de forma que haya constructores que solo se puedan usar desde dentro de la misma clase(private), clase derivada(protected), ensamblado(internal) ó por todo el mundo(public). Útil para controlar desde donde se pueden instanciar nuestros objetos, ó cuantas veces, como en el patrón Singleton.

Además, podemos definir un constructor estático, sin parámetros, sin modificadores de acceso, imposible de invocar directamente… pero que nos permite inicializar lo que queramos antes que nigún miembro de la clase, estático ó de instancia, sea usado.

Bien, en C# 3.0 la inicialización rápida de objetos, permiten inicializar las propiedades públicas de una clase de una pasada:

class MyControl : Control
{
    public String Field1 { get;  set; }
    public String Field2 { get;  set; }
    public String Field3 { get;  set; }
    public String Field4 { get; private set; }
}
 
static void Main()
{
    MyControl mc = new MyControl() { Field1 = "f1", Field2 = "f2", Field3 = "f3" };
}

No voy a discutir de lo útil que es, porque definitivamente lo es, pero por supuesto no es una caracteristica para reemplazar los constructores porque:

  • No podemos inicializar campos privados ó propiedades públicas con setter privado.
  • Puede que necesitamos ejecutar alguna lógica ó incluso otros métodos en función del tipo de parámetros.
  • No denota cuales son las propiedades que necesita tener configuradas para poder considerarse totalmente inicializado, de cara a alguien que consuma nuestra clase a posteriori. Esto me parece lo más importante, ya que el código debe intentar ser autodescriptivo.

Al igual que los métodos parciales, métodos extensores ó tipos anónimos, es una nueva caracteristica para tener en cuenta y para usar cuando sea apropiado, no viene a reemplazar nada, viene a complementar para “esos casos” donde hace falta.

Si tu clase necesita datos ó ser inicializada, implementa un constructor parametrizado. Por la salud mental de nuestros compañeros de trabajo, hagamos un buen uso del lenguaje 😀

Constructores, inicializacion rapida de objetos y C# 3.0 | vtortola.NET

3 comentarios en “Constructores, inicializacion rapida de objetos y C# 3.0”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *