lunes, 7 de octubre de 2013

Inicializadores de Objetos en C#

Tabla de Contenido

0. Introducción
1. Incializadores de Objetos
2. Inicializadores de Objetos en Tipos Anónimos
3. Inicializadores de Objetos con Tipos que Aceptan Tipos Nulos
4. Inicializadores en Colecciones
5. Inicializadores de Objetos versus Parámetros Opcionales
6. Conclusiones
7. Glosario
8. Referencias

0. Introducción

En varios de los artículos anteriores en los que el código fuente C# incluye instanciación de objetos de clase, observamos que la inicialización de un objeto se hace pasando/asignado valores a cada uno de los argumentos requeridos por la versión sobrecargada del constructor que estemos utilizando. En esta oportunidad les quiero presentar un acelerador de inicialización de objetos: incializadores de objetos.

1. Inicializadores de Objetos

Además de acelerar (he asignado este término debido a la facilidad y flexibilidad de acceso a elementos del miembro a la hora de crear un objeto), los inicializadores de objetos permiten omitir el proceso de invocación de uno de los constructor disponibles de la clase de contexto. Esto es permitido siempre y cuando los campos de instancia y las propiedades tengan visibilidad o acceso desde el exterior (e.gr., desde una clase cliente). Esta característica fue introducide en la versión 3.0 de C#.

Análogamente, los inicializadores de objeto permite invocar un constructor implícito en tiempo de ejecución.

Empiezo por mostrar un ejemplo sencillo de este interesante concepto de instanciación de objetos:

Archivo C# Laptop.cs [enlace alternativo]:
Es de esta manera como clásicamente inicializaríamos objetos de la clase Laptop (sólo dos posibilidades):

Laptop laptop1 = new Laptop ();
Laptop laptop2 = new Laptop ("Asus", "N73SV");

Hasta aquí, nada nuevo. Ahora pasemos a las siguientes líneas de código fuente C#:

Laptop laptop3 = new Laptop { Marca="HP", Procesador = "Intel Core i7 2630QM" };
Laptop laptop4 = new Laptop { TamanioPantalla = 17.4 };

Para la instancia laptop3 sólo inicializamos los campos Marca y Procesador , los demás (Procesador, y TamanioPantalla)  se inicializan con sus valores por defecto: 0.0D, null y respectivamente. Hay que resaltar que no es necesario especificar los paréntesis para el constructor sin parámetros; eso es lo que ocurre en las dos sentencias anteriores.

En línea con lo anterior, observemos este caso:

Laptop laptop5 = new Laptop ("HP", "G42") { Procesador = "Intel Core i3 370M", TamanioPantalla = 14.5 };

Hemos invocado la versión sobrecargada Laptop (string marca, string modelo) y además especificado valores de inicialización para los dos campos restantes.

Archivo C# AdministradorTI.cs [enlace alternativo]:
Gracias a las propiedades autoimplementadas [3], que básicamente consisten en la creación de un campo private anónimo autogenerado por medio de las propiedades [5] (en temas posteriores me extenderé en este tipo de miembro de clase); podemos inicializar un objeto así:

AdministradorTI adminTI = new AdministradorTI { Nombre = "Edward Ortiz Ordoñez", Sueldo = 6700000.00M };

2. Inicializadores de Objetos en Tipos Anónimos

A pesar de que la manipulación de expresiones de consulta basadas en LINQ [9] es un tema intermedio y de tratamiento posterior en diferentes artículos, vale la pena incursionar respecto a la utilidad de los inicializadores de objetos en la creación de este tipo de expresiones (y su relación y uso frecuente con la creación de tipos anónimos [5] (éstos sólo pueden ser inicializados con un objeto inicializador)).

Veamos:

var mascota = new { Edad = 5, Nombre = "Mateo" };

En esta expresión estamos creando un objeto anónimo con dos atributos Edad y Nombre. La utilidad de este tipo de expresión se haya, por un lado, en permitir realizar consultas sobre una expresión de consulta de LINQ. Es muy común que las consultas a una base de datos estén formadas de la extracción de datos para ciertos campos, por ejemplo:

var infoProductos = from p in productos select new { p.NombreProducto, p.PrecioUnitario };

Como la extracción es parcial: los campos NombreProducto y PrecioUnitario; ahora supóngase que la tabla Productos además cuenta con otros 6 campos; ahora crear 6 versiones sobrecargadas del constructor Producto puede resultar en un tarea que implique inicializaciones redudantes y baja cohesión.

3. Inicializadores de Objetos con Tipos que Aceptan Valores Nulos

De acuerdo con [2]:
It is a compile-time error to use an object initializer with a nullable struct.
Lo que en básicamente nos dice es que el compilador de C# generará un error en tiempo de compilación cuando se pretenda usar una estructura que admita valores nulos. Más acerca de este tema en [7].

4. Inicializadores en Colecciones

En colecciones como List [8] C# permite inicializar la lista utilizando la lista inicializadora de objetos:

List<string> nombres = new List<string> { "Juan", "Oliva", "Edward", "Germán", "Daniela" };
List<int> numeros = new List<int> { 25 + 1, 35 % 5, aleatorio.Next(), 8 };

5. Objetos Inicializadores versus Parámetros Opcionales

Los parámetros opciones también pueden ser utilizados en la firma de un constructor. Este es un medio alterno o análogo al uso de inicializadores de objetos.

En el ejemplo de la clase Laptop de arriba declaramos el siguiente constructor:

public Laptop (string marca, string modelo, string procesador = "Ninguno", double tamanioPantalla = 0.0)
{
Marca = marca;
Modelo = modelo;
Procesador = procesador;
TamanioPantalla = tamanioPantalla;
}

Esto nos da flexibilidad para crear un objeto con el siguiente perfil:

Laptop laptop6 = new Laptop( marca = "Lenovo", modelo = "G470", tamanioPantalla = 15.4);

6. Conclusiones

Los inicializadores es una poderosa herramienta que facilita al programador del lenguaje C# crear objetos con diferentes perfiles basados en inicialización de valores a una situación de declaración contextual. Se presentó, además, el uso de inicializadores de objetos en tipo anónimos, en especial con las expresiones de consulta de LINQ. Al finalizar, vimos la analogía y similitud entre un constructor con parámetros opcionales y un inicializador de objeto.

7. Glosario

  • Collección
  • Inicializador
  • Nullable
  • Tipo anónimo

8. Referencias

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: Object and Collection Initializers (C# Programming Guide) - http://msdn.microsoft.com/en-us/library/vstudio/bb384062.aspx
[3]: Auto-Implemented Properties (C# Programming Guide) - http://msdn.microsoft.com/en-us/library/vstudio/bb384054.aspx
[4]: Properties (C# Programming Guide) - http://msdn.microsoft.com/en-us/library/x9fsa0sw.aspx
[5]: Anonymous Types (C# Programming Guide) - http://msdn.microsoft.com/en-us/library/vstudio/bb397696.aspx
[6]: Patterns in Practice: Cohesion And Coupling - http://msdn.microsoft.com/en-us/magazine/cc947917.aspx
[7]: Nullable(T) Structure (System) - http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
[8]: List(T) Class (System.Collections.Generic) - http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx
[9]: LINQ (Language-Integrated Query) - http://msdn.microsoft.com/en-us/library/vstudio/bb397926.aspx


O

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.