viernes, 9 de mayo de 2014

Receta No. 2-11 en C#: Uso de una Colección con Tipos de Datos Específicos

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
4. Práctica: Código Fuente C#
5. Conclusiones
6. Glosario
7. Enlaces & Literatura

0. Introducción

Los conceptos que vamos a aprender en esta receta consisten en el tratamiento o manipulación de los elementos de una colección que corresponden con un tipo de dato específico. Con esto veremos que acotamos a un dominio de uso de datos de una categoría o naturaleza particular, de este modo, removemos ambigüedades o problemas de casting en operaciones comunes (agregación, remoción, actualización, lectura) sobre estructuras de datos genéricas. Nos convenceremos de que Microsoft .NET Framework provee el conjunto de estas estructuras para alcanzar el objetivo previamente mencionado.

1. Problema

Podríamos recurrir a un estructura de datos como ArrayList, Stack, o Queue (namespace System.Collections) para almacenar instancias de tipos de datos, sin embargo, estas estructuras no son apropiadas (para el caso que corresponde, por supuesto) debido a que pueden almacenar cualquier tipo de dato (System.Object) para una instancia particular de las clases mencionadas, y esto puede dar lugar problemas de casting (bueno, esto lo podríamos resolver haciendo uso de las construcciones de consulta de tipo previo a la conversión al tipo correspondiente, sin embargo puede resultar engorroso hacer este tipo de consulta por cada elemento almacenado en la estructura). Ergo, necesitamos una alternativa que acote la estructura de datos al almacenamiento específico de un tipo de dato.

2. Solución

Microsoft .NET Framework nos provee un nombre de espacios -System.Collections.Generic- con tipos (interfaces, clases, y estructuras) genéricos (en artículos posteriores hablaré acerca de Genéricos en C#). Con las estructuras de datos genéricas podemos especificar en tiempo de instanciación el tipo de dato que almacenará la estructura (con esto acotamos al ámbito de tipo que deseamos manipular). En [1] se recurre al concepto de Strongly Typed Collection.

3. Discusión de la Solución

Demos un vistazo al namespace System.Collections.Generic [3]. Este nombre de espacios posee los siguientes (sólo por nombrar algunos) tipos:
  • Clases:
    • Dictionary [4]
    • HashSet<T> [5]
    • LinkedList<T> [6]
    • List<T> [7]
    • Queue<T> [8]
    • Stack<T> [9]
  • Estructuras:
    • HashSet<T>.Enumerator
    • List<T>.Enumerator
    • Stack<T>.Enumerator
  • Interfaces:
    • ICollection<T>
    • IEnumerable<T>
    • IList<T>
La convención TipoEstructura<T> corresponde con el tipo de estructura -TipoEstructura- (lista (List), cola (Queue), diccionario (Dictionary), &c.), y   <T> corresponde con el especificador de tipos a almacenar en la estructura. (La T hace referencia al término anglosajón Template que su por primera vez en los lenguajes de programación orientados objetos de primera generación como C++).

Veamos un ejemplo de uso de la colección genérica Dictionary en C#:

Dictionary<string, string> asociacion = new Dictionary<string, string>();

En resumen, hemos creado un estructura diccionario que concuerda con un tipo de llave (key) string, y un tipo de valor (value) string. Es decir, que este diccionario sólo almacenará tipos string para los tipos parmétricos (esto gracias a la genericidad).

Ahora agreguemos elementos al diccionario:

asociacion.Add("mp3", "winamp.exe");
asociacion.Add("png", "IrfanViewPortable.exe");
asociacion.Add("cs", "Notepad++Portable.exe");
asociacion.Add("html", "FirefoxPortable.exe");
asociacion.Add("torrent", "uTorrentPortable.exe");

Estas líneas de código serán compiladas correctamente. Pero, si especificamos algo como esto:

asociacion.Add("mht", new System.Object());

El compilador generará los siguientes errores relacionados con el intento de especificar un valor System.Object:

Error CS1502 [10]:
error CS1502: The best overloaded method match for `System.Collections.Generic.Dictionary.Add(string, string)' has some invalid arguments

Error CS1503 [11]:

error CS1503: Argument `#2' cannot convert `object' expression to type `string'

4. Práctica: Código Fuente C#

Veamos el uso de las estructuras de datos Dictionary<TKey><TValue>List<T> en el siguiente ejemplo:

Archivo Genericos.cs:

Observe que en la línea 59:

double pi = listConstMatematicas[2];


gracias a que listConstMatematicas sólo contiene valores de tipo double (List<double>) podemos asignar el valor de la posición 2 de lista directamente sobre la variable pi (double).


> Prueba de ejecución.

Resultado:

Contenido del diccionario `constMatematicas`:
 Nombre constante: Constante de Euler, Valor constante: 0.577215664901
 Nombre constante: Media aureal, Valor constante: 1.618033988
 Nombre constante: Pi, Valor constante: 3.14159265358979
 Nombre constante: Raíz de 2, Valor constante: 1.414213562

Constantes en la lista genérica `listConstMatematicas`:
 Constante matemática: 0.577215664901
 Constante matemática: 1.618033988
 Constante matemática: 3.14159265358979
 Constante matemática: 2.71828182845905
 Constante matemática: 1.414213562

5. Conclusiones

Podemos concluir que el trabajo sobre estructuras de datos genéricas facilita el desarrollo, específicamente, en la manipulación de datos en la memoria de trabajo; además reduce el número de errores en conversiones gracias a que las asignaciones en memoria corresponde con un tipo de dato específico de la estructura de datos.

6. Glosario

  • Casting
  • Colección
  • Collection
  • Genericidad
  • Genérico
  • Estructuras de datos
  • Tipo de dato

7. Enlaces & Literatura

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: ArrayList Class (System.Collections) - http://msdn.microsoft.com/en-us/library/system.collections.arraylist%28v=VS.100%29.aspx
[3]: System.Collections.Generic Namespace () - http://msdn.microsoft.com/en-us/library/system.collections.generic%28v=vs.110%29.aspx
[4]: Dictionary(TKey, TValue) Class (System.Collections.Generic) - http://msdn.microsoft.com/en-us/library/xfhwa508%28v=vs.110%29.aspx
[5]: HashSet(T) Class (System.Collections.Generic) - http://msdn.microsoft.com/en-us/library/xfhwa508%28v=vs.110%29.aspx
[6]: LinkedList(T) Class (System.Collections.Generic) - http://msdn.microsoft.com/en-us/library/he2s3bh7%28v=vs.110%29.aspx
[7]: List(T) Class (System.Collections.Generic) - http://msdn.microsoft.com/en-us/library/6sh2ey19%28v=vs.110%29.aspx
[8]: Queue(T) Class (System.Collections.Generic) - http://msdn.microsoft.com/en-us/library/7977ey2c%28v=vs.110%29.aspx
[9]: Stack(T) Class (System.Collections.Generic) - http://msdn.microsoft.com/en-us/library/3278tedw%28v=vs.110%29.aspx
[10]: Compiler Error CS1502 - http://msdn.microsoft.com/en-us/library/b66k5sz9.aspx
[11]: Compiler Error CS1503 - http://msdn.microsoft.com/en-us/library/8zf99ds2%28v=vs.90%29.aspx


M

No hay comentarios:

Publicar un comentario

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