InicioArticulos y noticiasBases de datosProgramaciónForosInternetServiciosContratacionEmail
Tutorial C#
Introduccion a C#
Programacion con C#
Fundamentos de C#
Operadores
Instrucciones
Estrcuturas de control.
Definición de clases
Creación de objetos
Herencia y métodos virtuales
Polimorfismo
Ocultación de miembros
Miembros de tipo
Encapsulación
Espacios de nombres
Importación de espacios de nombres
Espacio de nombres distribuidos
Variables y tipos de datos
Tablas unidimensionales
Tablas multidimensionales
La clase System.Array
Cadenas de texto
Constantes
Orden de inicialización de variables
Métodos
Métodos externos
Constructores
Destructores
Propiedades
Indizadores
Redefinición de operadores
Delegados y eventos
La clase MulticastDelegate
Llamadas asíncronas
Implementación interna de los delegados
Eventos
Estructuras
Boxing y unboxing
Constructores de estructuras
Enumeraciones
Interfaces
Excepciones
Otras instrucciones
Atributos
Definición de nuevos atributos
Lectura de atributos en tiempo de ejecución
Atributos de compilación
Pseudoatributos
Código inseguro
Definición de punteros
Manipulación de punteros
Operadores relacionados con código inseguro
Fijación de variables apuntadas
Novedades de C# 2.0
Genéricos
Tipos parciales
Iteradores
Mejoras en la manipulación de delegados
Tipos anulables
Modificadores de visibilidad de bloques get y set
Clases estáticas
Referencias a espacios de nombres
Supresión temporal de avisos
Atributos condicionales
Incrustación de tablas en estructuras
Modificaciones en el compilador
También puedes ver ...
Creando cadenas de conexión ConnectionStrings en .net 3.5 o visual Studio 2008 usando SqlConnectionStringBuilder
Migración de WSE a WCF (Web Services de 2005 a 2008)
Generar archivos PDF con C#
TransactionScope - Simplificando el trabajo con transacciones.
LinQ To SQL - Un ejemplo sencillo
Cómo activar Intelisense (autocompletado) en el Web.config
Leer un campo XML de SQL Server 2005 con C#
TripleDES - Un ejemplo practico en C#
Mostrar un GridView dentro de un DataList
String.Format

Afiliados
La Web del programador
MundoProgramacion


 

Iteradores

    Aprovechando las ventajas proporcionadas por los genéricos, en la BCL del .NET 2.0 se ha optimizado la implementación de las colecciones introduciendo en un nuevo espacio de nombres System.Collections.Generic dos nuevas interfaces llamadas IEnumerable<T> e IEnumerator<T> que las colecciones podrán implementar para conseguir que el acceso a las colecciones sea mucho más eficiente que con las viejas IEnumerable e IEnumerator al evitarse el boxing/unboxing o downcasting/upcasting que el tipo de retorno object de la propiedad Current de IEnumerator implicaba. Además, en ellas se ha optimizado el diseño eliminando el tan poco utilizado método Reset() y haciéndoles implementar en su lugar la estandarizada interfaz IDisposable. En resumen, están definidas como sigue:


 public interface IEnumerable<T>
 {
   IEnumerator<T> GetEnumerator();
 }
 
 public interface IEnumerator<T>: IDisposable
 {
   T Current { get; }
   bool MoveNext();
 }
 

     Nótese que en realidad C# 1.0 ya proporcionaba a través del patrón de colección un mecanismo con que implementar colecciones fuertemente tipadas. Sin embargo, era algo específico de este lenguaje, oculto y desconocido para muchos programadores y no completamente soportado por otros lenguajes .NET (por ejemplo, Visual Basic.NET y su sentencia For Each) Por el contrario, estas nuevas interfaces genéricas proporcionan una solución más compatible y mejor formulada.

     C# 2.0 proporciona además un nuevo mecanismo con el que es resultará mucho sencillo crear colecciones que implementando directamente estas interfaces: los iteradores. Son métodos que para generar objetos que implementen todas estas interfaces se apoyan en una nueva sentencia yield. Han de tener como tipo de retorno IEnumerable, IEnumerator, IEnumerable<T> e IEnumerator<T>, y su cuerpo indicarán los valores a recorrer con sentencias yield return <valor>; en las que si se el tipo de retorno del iterador es genérico, <valor> deberá ser de tipo T. Asimismo, también se marcar el fin de la enumeración y forzar a que MoveNext() siempre devuelva false mediante sentencias yield break;.

    A partir de la definición de un iterador, el compilador anidará dentro de la clase en que éste se definió una clase privada que implementará la interfaz de su tipo de retorno. El código del iterador no se ejecutará al llamarle, sino en cada llamada realizada al  método MoveNext() del objeto que devuelve, y sólo hasta llegarse a algún yield return. Luego la ejecución se suspenderá hasta la siguiente llamada a MoveNext(), que la reanudará  por donde se quedó. Por tanto, sucesivas llamadas a MoveNext() irán devolviendo los valores indicados por los yield return en el mismo orden en que se éstos se ejecuten. Así, en:


 using System;
 using System.Collections;
 
 class PruebaIteradores
 {
     public IEnumerator GetEnumerator()
     {
       yield return 1;
       yield return "Hola";
     }
 
     public IEnumerable AlRevés
     {
       get
         {
            yield return "Hola";
            yield return 1;
      }
     }
 
     static void Main()
     {
       PruebaIteradores objeto = new PruebaIteradores();
       foreach(object valor in objeto)
           Console.WriteLine(valor);
 
       foreach(object x in objeto.AlRevés)
           Console.WriteLine(x);
     }
 }

    La clase PruebaIteradores tendrán un método GetEnumerator() que devolverá un objeto IEnumerator generado en base a las instrucciones yield que retornará como primer elemento un 1 y como segundo la cadena "Hola", por lo que podrá ser recorrida a través de la instrucción foreach. Del mismo modo, su propiedad AlRevés devolverá un objeto que también dispone de dicho método y por tanto también podrá recorrese a través de dicha sentencia, aunque en este caso hace el recorrido al revés. Por tanto, su salida será:

 1

 Hola

 Hola

 1

    Nótese que aunque los iteradores se puedan usar para definir métodos que devuelvan tanto objetos IEnumerable como IEnumerator, ello no significa que dichos tipos sean intercambiables. Es decir, si en el ejemplo anterior hubiésemos definido la propiedad AlRevés como de tipo IEnumerator, el código no compilaría en tanto que lo que foreach espera es un objeto que implemente IEnumerable, y no un IEnumerator.

    En realidad, si el tipo de retorno del iterador es IEnumerator o IEnumerator<T>, la clase interna que se generará implementará tanto la versión genérica de esta interfaz como la que no lo es. Lo mismo ocurre para el caso de IEnumerable e IEnumerable<T>, en el que además, el compilador opcionalmente (el de C# de Microsoft sí lo hace) también podrá implementar las interfaces IEnumerator e IEnumerator<T>. Sin embargo, implementar las interfaces IEnumerator no implica que se implementen las IEnumerable, y de ahí el problema descrito en el párrafo anterior.

    Por otro lado, hay que señalar que en el código que se puede incluir dentro de los iteradores existen algunas limitaciones destinadas a evitar rupturas descontroladas de la iteración: no se permiten sentencias return, ni código inseguro ni parámetros por referencia, y las sentencias yield no se puede usar dentro de bloques try, catch o finally.

    Internamente, a partir de la definición del iterador el compilador generará una clase interna que implementará la interfaz del tipo de retorno de éste y sustituirá el código del miembro de la colección donde se define el iterador por una instanciación de dicha clase a la que le pasará como parámetro el propio objeto colección a recorrer (this) En ella, el código del iterador se transformará en una implementación del MoveNext() de IEnumerator basada en un algoritmo de máquina de estado, y la posible limpieza de los recursos consumido por la misma se hará en el Dispose() O sea, se generará algo como:


 public class <colección>:<interfaz>
 {
  public virtual <interfaz> GetEnumerator() 
  { 
   return    GetEnumerator$<númeroAleatorioÚnico>__IEnumeratorImpl impl = 
   new GetEnumerator$<númeroAleatorioÚnico>__IEnumeratorImpl(this);  
  }
   
  class GetEnumerator$<númeroAleatorioÚnico>__IEnumeratorImpl:<interfaz>
  {
   public <colección> @this;
   <tipoElementosColección> $_current;  
   string <interfaz>.Current { get { return $_current; } }
   
   bool <interfaz>.MoveNext()
   {
    // Implementación de la máquina de estados
   }
   
   void IDisposable.Dispose()
   {
    // Posible limpieza de la máquina de estados
   }
  }
 }

    Nótese que para cada foreach se generará un nuevo objeto de la clase interna, por lo que el estado de estos iteradores automáticamente generados no se comparte entre foreachs y por tanto el antiguo método Reset() de IEnumerator se vuelve innecesario. Es más, si la interfaz de retorno del iterador fuese IEnumerator, la implementación realizada por el compilador en la clase interna para el obsoleto método de la misma Reset() lanzará una NotSupportedException ante cualquier llamada que explícitamente se le realice. No obstante, hay que tener cuidado con esto pues puede implicar la creación de numerosos objetos en implementaciones recursivas como la siguiente, en la que se aprovechan los iteradores para simplificar la implementación de los recorridos sobre un árbol binario:


 using System.Collections.Generic;
 
 public class Nodo<T>
 {
  public Nodo<T> Izquierdo, Derecho;
  public T Valor;
 }
 
 public class ÁrbolBinario<T>
 {
  Nodo<T> raíz;
  public IEnumerable<T> Inorden{get{return recorrerEnInorden(this.raíz); } }
  IEnumerable<T> recorrerEnInorden(Nodo<T> nodo)
  {
   Nodo<T> nodoIzquierdo = nodo.Izquierdo;
   if (nodoIzquierdo!=null)
    foreach(T valor in recorrerEnInorden(nodoIzquierdo))
     yield return valor;
                        
   yield return raíz.Valor;
   Nodo<T> nodoDerecho= nodo.Derecho;
   if (nodoDerecho!=null)
    foreach(T valor in recorrerEnInorden(nodoDerecho))
     yield return valor;
  }
 
 // Implementación de recorridos en Preorden y PostOrden y demás miembros
 }


Inicio | Tutorial C# Tipos parcialesTutorial C#Mejoras en la manipulación de delegados Versión para imprimir Foros de consulta


Añadir comentario ... Para preguntar utiliza los foros
Autor:

Título:


Para preguntar utiliza los foros.



Inicio | Tutorial C# Tipos parcialesTutorial C#Mejoras en la manipulación de delegados Versión para imprimir

Iteradores
Autor: José Antonio González Seco
Visitas: 5073 Fecha de publicación: 01/01/2007
José Antonio es experto en tecnologias Microsoft. Imparte cursos y conferencias en congresos sobre C# y .NET en Universidades de toda España (Sevilla, Barcelona, San Sebastián, Valencia, Oviedo, etc.) en representación de grandes empresas como Microsoft.




Visitas: 328 | Comentarios: 0 | Archivo: Articulos
Categorias: Visual Basic .NET|C#|ASP.NET|ASP.NET|Programación|ADO.NET
27/09/2008 Navegando ....
Visitas: 87 | Comentarios: 0 | Archivo: Articulos
Categorias: Humor
Visitas: 210 | Comentarios: 0 | Archivo: Articulos
Categorias: Visual Basic .NET|C#|ASP.NET|ASP.NET|Programación|WCF
Visitas: 954 | Comentarios: 0 | Archivo: Articulos
Categorias: C#
Visitas: 209 | Comentarios: 0 | Archivo: Articulos
Categorias: JavaScript|ASP.NET
Visitas: 682 | Comentarios: 0 | Archivo: Articulos
Categorias: Windows XP|Linux|Windows Vista
Visitas: 458 | Comentarios: 0 | Archivo: Articulos
Categorias: Linux|BSD
Visitas: 238 | Comentarios: 0 | Archivo: Articulos
Categorias: Programación|Actualidad
18/08/2008 SQL Server 2008
Visitas: 1151 | Comentarios: 1 | Archivo: Articulos
Categorias: Transact-SQL
Visitas: 797 | Comentarios: 0 | Archivo: Articulos
Categorias: C#|ADO.NET|LinQ

Útimos temas recibidos en los foros ...
yo por nikoo ... [C#] 0 11/10/2008
Manual Visual Studio.NET por Shiko ... [Visual Basic .NET] 19 26/10/2006
conexión a LDAP por mari90 ... [ASP.NET] 21 05/02/2007
Coastal Inversiones SAC Coastal Vacations Oportunidad de Negocios por lecasur ... [ASP.NET] 1 11/10/2008
hacer el nombre de una tabla variable por leicolei ... [SQL Server] 2 10/10/2008
ayuda por yo ... [C#] 2 09/10/2008
Mostar nombre en una sesion de usuario por jhors ... [ASP.NET] 1 10/10/2008
Analista por Rolando ... [SQL Server] 0 10/10/2008
SQL dinámico en TRIGGERS por Alastor ... [ORACLE] 2 03/10/2008
Crystal Reports 8.5 por selvinalberto ... [Visual Basic 6.0] 0 10/10/2008
Agregar Columnas a un datagridview por Tony ... [Visual Basic .NET] 3 20/11/2007
Problema cargando un pl/sql Embebido en Pro*C por ejrivas ... [ORACLE] 0 10/10/2008

Access CGI JSP ORACLE UNIX
Actualidad HTML/DHTML/XHTML LINUX PHP Visual Basic .NET
ASP ISAPI MS DOS Power Builder Visual Basic 6.0
ASP.NET Java mySQL SQL WIN 98/NT/2000/XP
C# JavaScript Opinion SQL Server

devjoker  Te recomendamos además ...
20/07/2006 Transacciones con PL/SQL    forma parte de...Tutorial PL/SQL
08/09/2007 Funciones en Transact SQL    forma parte de...Tutorial de Transact SQL
26/07/2006 Secuencias    forma parte de...Tutorial PL/SQL
28/06/2006 Procedimientos almacenados en PL/SQL    forma parte de...Tutorial PL/SQL
29/09/2006 Common Type System (CTS)    forma parte de...Conceptos generales .NET
22/10/2005 Actualización de datos. UPDATE    forma parte de...Tutorial SQL
24/05/2006 Cursores Explicitos en PL/SQL    forma parte de...Tutorial PL/SQL
24/05/2006 Cursores Implicitos en PL/SQL    forma parte de...Tutorial PL/SQL
23/05/2006 Cursores en PL/SQL    forma parte de...Tutorial PL/SQL
04/03/2006 Bloques PL/SQL    forma parte de...Tutorial PL/SQL

 

Encuesta
¿A que perfil te adaptas mejor?
[Ver] [Votar]