C# yield: tutorial paso a paso sobre colecciones perezosas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué necesitas yield en C#? El secreto de las colecciones perezosas



Imagina: estás escribiendo un método que debe devolver una lista de números del 1 al millón. Lo primero que viene a la mente es crear un List<int>, llenarlo y devolverlo. Pero, ¿qué pasa si el código que llama solo quiere los primeros 10 elementos? De todas formas, perdiste tiempo creando un millón de objetos, ocupaste memoria y todo fue en vano.



Aquí entra en escena la palabra clave yield en C#. No es solo azúcar sintáctico, sino una herramienta poderosa para crear secuencias perezosas (lazy). En este artículo analizaremos yield return y yield break con ejemplos reales, entenderemos cómo funcionan internamente y aprenderemos a aplicarlos en el desarrollo diario.



Este tutorial está basado en una pregunta real de Stack Overflow que acumuló miles de visitas. Lo hemos adaptado para contenido educativo, añadiendo ejemplos de código C# paso a paso y consejos prácticos útiles.



¿Qué es yield en C#? En palabras sencillas



yield es una palabra clave contextual en C# que le indica al compilador: "Este método es un iterador". Cuando escribes yield return, el método no se ejecuta todo de una vez. En cambio, devuelve los elementos uno por uno, cuando el código que llama los solicita. Esto se llama ejecución perezosa.



A diferencia del return normal, que finaliza el método, yield return pausa el método, guarda su estado y devuelve el elemento actual. En la siguiente llamada, el método continúa desde donde se detuvo.



Sintaxis: yield return y yield break



En C# hay dos formas de yield:



  • yield return — devuelve el siguiente elemento de la secuencia.
  • yield break — finaliza inmediatamente la iteración (como break en un bucle).


El método que usa yield debe devolver uno de estos tipos:

  • IEnumerable<T>
  • IEnumerable
  • IAsyncEnumerable<T> (a partir de C# 8.0)
  • IEnumerator<T> o IEnumerator


Primer ejemplo: de lo simple a lo complejo



Escribamos un iterador muy simple que genere números del 1 al 5:



public static IEnumerable<int> GetNumbers(){    yield return 1;    yield return 2;    yield return 3;    yield return 4;    yield return 5;}

// Uso:foreach (int number in GetNumbers()){ Console.WriteLine(number);}


Salida:

12345


A primera vista, esto se parece a una lista normal. Pero la diferencia es enorme: cada elemento se genera solo cuando foreach lo solicita. ¡Nada de asignar memoria para toda la lista!



¿Cómo funciona internamente?



El compilador de C# convierte el método con yield en un autómata de estados (state machine) completo. Crea una clase que implementa IEnumerable<T> e IEnumerator<T>. Esta clase almacena:

  • El estado actual (en qué línea del método nos detuvimos).
  • Las variables locales del método.
  • Una referencia al objeto actual (this), si el método no es estático.


Cada vez que se llama a MoveNext() (y esto lo hace foreach), el autómata de estados reanuda la ejecución desde donde se detuvo por última vez.



Ejemplo real: lectura de un archivo grande



Imagina que necesitas procesar un archivo de registros de 10 GB. Si lo lees completo en memoria, el programa fallará con un OutOfMemoryException. Con yield puedes leer el archivo línea por línea y procesar cada línea sobre la marcha:



public static IEnumerable<s                

Blogs

Book Recommendations