lunes, 6 de abril de 2015

Tipos Anónimos en C#

Índice

0. Introducción
1. Tipo Anónimo
2. Traducción de un Tipo Anónimo
3. LINQ y Tipos Anónimos
4. Características Extra de Tipos Anónimos
4.1 Determinación de identificadores
4.2 Tipos anónimos idénticos
4.3 Sobreescritura del método Equals
5. Reglas y Comentarios de Tipos Anónimos
6. Conclusiones
7. Glosario
8. Literatura & Enlaces

0. Introducción

En este artículo estudiáremos con detalle el uso y propósito de tipos anónimos. Este tipo de construcción de C#, como veremos, nos facilitará la definición de miembros de tipo (exactamente, propiedades de sólo lectura) sin recurrir a la definición explícita de una clase o estructura en tiempo de diseño. Esta tarea la realizará automáticamente el compilador de C#. A través de ejemplos de uso entenderemos que su utilidad principal está orientada a la construcción o diseño de consultas LINQ.

1. Tipo Anónimo

Un tipo anónimo es el resultado de definición de una clase sin nombre con únicamente propiedades de sólo lectura por parte del compilador. Este trabajo que realiza el compilador de forma automática requiere de definiciones básicas y sencillas de valores de otros tipos de datos por parte del programador; para lograrlo, se debe recurrir a estas construcciones del lenguaje:
  • La palabra clave new
  • Inicializador de objetos [2]
var tipoDesconocido = new { Nombre = "Fedor", Edad = 30 }; 

En primer lugar se define el tipo de la variable tipoDesconocido con var; luego utilizamos el operador new seguido de un objeto de inicialización, que en este caso tiene definidos dos propiedades con nombres formales. El compilador de C# se encargará de inferir los tipos de los datos basado en los valores asignados a las propiedades de sólo lectura:
  • Nombre: String
  • Edad: int

Vale agregar que en Visual Studio podemos reconocer los tipos asociados de las propiedades del tipo anónimo en tiempo de diseño. Para el ejemplo de uso anterior:
Inferencia de tipos en Visual Studio
Figura 1. Inferencia de tipos de propiedades de tipo anónimo en Visual Studio.

2. Traducción de un Tipo Anónimo

Ya hemos mencionado que el compilador de C# es capaz de inferir los tipos de las propiedades basado en el tipo de los valores asignados. Sin embargo, es importante tener conocimiento de lo que sucede detrás de cámaras: reconocer la traducción aproximada que lleva a cabo el compilador a partir de un tipo anónimo. Veamos:

Notemos como en la línea 1 se declara la clase como el modificador internal junto con el nombre generado por el compilador. (NombreTipoAnonimoGenerado es sólo un nombre ilustrativo.) Sobre las líneas 3-4 se definen los campos de miembro con los tipos inferidos (i.e., stringint). También se define el constructor (líneas 6-10) con los parámetros formales y los tipos inferidos. Se defininen, además las propiedades que corresponden con los nombres (capitalizados) y tipos inferidos. En [1] añaden que los métodos miembro GetHashCode, Equals, y ToString son sobreescritos con versiones e implementaciones propias del tipo anónimo.


Para extendernos un poco más: cuando creamos un tipo anónimo, la traducción hecha por el compilador quedaría expresada de la siguiente manera:


var tipoDesconocido = new NombreTipoAnonimoGenerado ("Fedor", 30 );

3. LINQ y Tipos Anónimos

El lenguaje integrado de consulta (LINQ [5]) además de poseer capacidades abstractas para consultar datos sobre distintas fuentes de datos (e.g., objetos, bases de datos, XML), recurre al uso de tipos anónimos para la construcción implícita de objetos con las propiedades de los resultados de las consultas efectuadas a una fuente de datos.


Para ilustrar con código fuente C# la definición anterior, escribamos este ejemplo que consta de un arreglo de tipos anónimos y que para facilitar su manejo lo llamaremos personas; así:


var personas = new[]
{
new { Id = 1001, Nombre = "Vallejo" },
new { Id = 1002, Nombre = "Asimov" },
new { Id = 1003, Nombre = "Fedor" }
}

foreach (var persona in personas)
{
Console.WriteLine("ID: {0}", persona.Id);
Console.WriteLine("Nombre: {0}", persona.Nombre);
}


Además de iterar la lista de elementos de tipos anónimos podemos crear una consulta LINQ para enlistar cada uno de los datos asociados a la persona (i.e., Id, Nombre):


var resultado = from persona in personas
select new { persona.Id, persona.Nombre };


En esta sentencia de LINQ, exactamente en new { persona.Id, persona.Nombre } se crea de manera implícita un tipo anónimo con las propiedades Id, y Nombre por cada elemento en personas. A partir de aquí el compilador de C# realiza el mismo proceso iterativo de traducción a un tipo anónimo similar al que se ilustró en la sección anterior.

4. Características Extra de Tipos Anónimos

4.1 Determinación de identificadores

Podemos especificar variables ya definidas y hacerlas parte del objeto de inicialización para la creación de un tipo anónimo. Esto lo logramos simplemente incluyendo en la lista de inicialización uno o más variables de tipos conocidos previamente definidas:

int Edad = 30;
var tipoAnonimo = new { Nombre = "Fedor", Edad, Edad.ToString().Length };

El segundo elemento de la lista de inicialización, Edad, se convertirá en una propiedad del objeto anónimo. Esta misma operación también ocurrirá para la propiedad Length de String.

4.2 Tipos anónimos identicos

Dos tipos anónimos son idénticos o iguales si cumplen con las siguientes características:
  • Las propiedades enlistadas tienen exactamente los mismos tipos de datos subyacentes.
  • Los nombres de las propiedades son idénticos.
Ilustremos esta característica con el siguiente ejemplo:

var tipoAnonimo1 = new { X = 2, Y = 4 };
var tipoAnonimo2 = new { X = 2, Y = 4 };

Console.WriteLine( tipoAnonimo1.GetType() == tipoAnonimo2.GetType() ); // True

4.3 Sobreescritura del método Equals

El método Equals [6] es sobreescrito por el compilador y funciona de la siguiente manera:

Console.WriteLine( tipoAnonimo1 == tipoAnonimo2 ); // False
Console.WriteLine( tipoAnonimo1.Equals(tipoAnonimo2) ); // True

5. Reglas y Comentarios de Tipos Anónimos

Estas son algunas reglas y comentarios extra de tipos anónimos [3]:
  • Todo tipo anónimo deriva directamente de object [6].
  • El compilador crea un nombre para cada tipo anónimo que es innaccesible en tiempo de diseño.
  • La CLR considera todo tipo anónimo de forma análoga a los tipos concretos o definidos por el programador.
  • No es posible declarar un campo, una propiedad, un evento [7], o tipo de retorno como tipo anónimo.
  • Los parámetros formales de un método, propiedad, constructor, o índice no admiten tipos anónimos.
  • Hay que considerar que el uso excesivo de tipos anónimos va en contra de la propiedad innata de C#: tipeado fuerte.

6. Conclusiones

Hemos explorado los fundamentos de tipos anónimos. Este tipo de construcciones, como hemos visto, nos facilita la composición de tipos de datos existencia o acción efímera. Su poderosa utilidad reside en la composición de consultas bajo el lenguaje de consulta integrado LINQ. Uno de los aspectos a reconocer está la traducción (aproximada) que hace el compilador para su tratamiento interno bajo la CLR. Al final exploramos otras características relevantes, además de reglas y comentarios de uso de tipos anónimos (e.g., la derivación directa de object.). En el próximo artículo C# descubriremos la vinculación dinámica (dynamic binding) en C#.

7. Glosario

  • CLR
  • LINQ
  • Tipeado fuerte
  • Tipo
  • Tipo anónimo

8. Literatura & Enlaces

[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]: Inicializadores de Objetos en C# - http://ortizol.blogspot.com/2013/10/inicializadores-de-objetos-en-c.html
[3]: Anonymous Types (C# Programming Guide) - https://msdn.microsoft.com/en-us/library/bb397696.aspx?f=255&MSPPError=-2147217396
[4]: Anonymous types - http://www.codeproject.com/Tips/133941/Anonymous-types
[5]: Language Integrated Query - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/Language_Integrated_Query
[6]: La Clase Object y sus Miembros en C# - http://ortizol.blogspot.com/2014/04/la-clase-object-y-sus-miembros-en-c.html
[7]: Eventos en C# - Parte 1: Introducción a Eventos - http://ortizol.blogspot.com/2014/06/eventos-en-csharp-parte-1-introduccion-a-eventos.html


J

No hay comentarios:

Publicar un comentario

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