domingo, 13 de agosto de 2017

Enumeración e Interfaces IEnumerator(T) e IEnumerable(T) en C#

Índice

1. Introducción
2. Palabras Clave
3. Interfaz IEnumerable<T>
4. Interfaz IEnumerator<T>
5. Implementación de Interfaces de Enumeración
6. Ejemplo de Uso
7. Conclusiones
8. Literatura & Enlaces

1. Introducción

En el artículo anterior se presentaron las versiones no-genéricas de las interfaces IEnumerable y IEnumerator; ahora, llega la oportunidad de estudiar la utilidad y uso de las versiones genéricas: IEnumerable<T> y IEnumerator<T>. El ejemplo de uso que se presentará al final del artículo pretendenrán ser lo más explícito posibles, sin embargo se mantendrá la simplicidad en el código.

2. Palabras Clave

  • Clase genérica
  • Colección
  • Estructura de datos
  • Interfaz

3. Interfaz IEnumerable<T>

La interfaz IEnumerable<T> ("IEnumerable(T)", 2017) proporciona a un tipo de dato que represente una colección la capacidad de recorrer sus elementos en modo lectura. Principalmente esta interfaz está diseñada para trabajar con genericidad: la estructura o colección será capaz de enumerar o listar los elementos independiente del tipo de dato particular especificado para el tipo paramétrico.

Pongamos como ejemplo la clase List<T> ("List(T) Class", 2017). Esta clase permite especificar un tipo de dato concreto a almacenar en la estructura; así:

List<Tipo> lista = new List<Tipo>();

El tipo paramétrico Tipo será el tipo de dato de los elementos que se almacenen en la variable lista.

Supongamos ahora que agregamos elementos a la lista:

lista.add(new Tipo(...));
lista.add(new Tipo(...));
lista.add(new Tipo(...));
//...
lista.add(new Tipo(...));

Para recorrer la lista el programador puede usar el ciclo foreach:

foreach(Tipo tipo in lista){
    // ...
}

En el cuerpo del ciclo foreach se puede llevar a cabo operaciones de solo lectura sobre la colección almacenada en lista:List<T>.

Otras clases de colecciones que implementan esta interfaz:
  • Dictionary<TKey, TValue>
  • Stack<T>

4. Interfaz IEnumerator<T>

A través de la interfaz IEnumerator<T> ("IEnumerator(T) Interface", 2017) permite implementar la iteración o enumeración de los elementos de una colección de tipos genéricos. Vale enunciar que esta interfaz genérica herada de IEnumerator (Enumeración e Interfaces IEnumerator e IEnumerable en C#); esto se observa en la siguiente figura:
Jerarquía de herencia de enumeadores genéricos
Figura 1. Jerarquía de herencia de enumeadores genéricos (Albahari, 2012).
Al igual que su contraparte no genérica, las colecciones que implementan esta interfaz tienen habilitada la iteración de sus elementos a través del ciclo foreach. C# lo que hace es ocultar los detalles de la iteración de los elementos a través de esta versión del loop for.

Continuando, IEnumerator<T> implementa la interfaz IDisposable, permitiendo al proceso de enumeración llevar control de referencias a recursos de conexión a datos, y asegurar que éstos liberen los recursos utilizados cuando hayan terminado su ejecución (Albahari, 2012). Cuando se usa el ciclo foreach como en 

foreach(Tipo tipo in lista){
    // ...
}

internamente se está llevando a cabo la siguiente equivalencia

using(var enumerador = lista.GetEnumerator()){
    while(enumerador.MoveNext()){
        // ...
    }
}

5. Implementación Intefaces de Enumeración

En Albahari (2012) se exponen motivacionees para implementar estas interfaces:
  • Soportar el ciclo foreach
  • Interoperar con elementos de programa que requieran de una colección estándar
  • Soportar inicializadores de colecciones
  • Cumplir los requerimientos de interfaces de colecciones más avanzadas

6. Ejemplo de Uso

El siguiente ejemplo de uso permite demostrar cómo crear una colección personalizada, llamada Lista, con un tipo paramétrico. El constructor de esta clase permite establecer el número de elementos que contendrá la colección; y además, contiene un método para agregar elementos: void AgregarElemento(T).

Este código se compila y se ejecuta de la siguiente manera:

csc /out:Coleccion.exe Coleccion.cs

./Coleccion.exe


El resultado de la ejecución:

Dostoevsky
Balzac
Dickens


El código se puede probar en:

http://ideone.com/PvBaTX

7. Conclusiones

Este artículo aprendimos a distinguir la utilidad esencial de las interfaces IEnumerator y IEnumerable en sus versiones genéricas. Notamos que proveen al programador los mecanismos generales para iterar una colección que acepta tipos paramétricos para almacenar en su estructura de datos. El ejemplo es presentando tuvo como objetivo dar un vistazo general sobre cómo implementar la interfaz IEnumerable<T>, y retornar un objeto IEnumerator<T>.

El próximo artículo lo dedicaremos a estudiar las interfaces ICollection y IList.

8. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.

A Beginner's Tutorial on Implementing IEnumerable Interface and Understanding yield Keyword - CodeProject (2017). Recuperado desde: https://www.codeproject.com/Articles/474678/A-Beginners-Tutorial-on-Implementing-IEnumerable-I
IEnumerable(T) Interface (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/9eekhta0%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
List(T) Class (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/6sh2ey19(v=vs.110).aspx
IEnumerator(T) Interface (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/78dfe2yb(v=vs.110).aspx
Enumeración e Interfaces IEnumerator e IEnumerable en C# (2017). Recuperado desde: https://ortizol.blogspot.com/2017/08/enumeracion-e-interfaces-ienumerator-e-ienumerable-en-csharp.html


J

No hay comentarios:

Publicar un comentario

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