Yield return en C#: magia perezosa para principiantes

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

Yield return en C#: cuando el código funciona "perezosamente" y es genial

\n\n

Imagina que estás escribiendo un programa que debe procesar un millón de líneas de un archivo de registro. Cargas honestamente todo en una lista List<string>, la pasas a un método de filtrado, y luego —¡pum!— el programa se congela, la memoria se fuga y el usuario presiona nerviosamente Ctrl+Alt+Del.

\n\n

¿Te suena familiar? Si alguna vez te has enfrentado a esta situación, entonces es hora de que conozcas la "magia perezosa" de C#: el operador yield return. No es solo azúcar sintáctico, sino una herramienta poderosa que puede cambiar radicalmente la forma en que trabajas con colecciones.

\n\n

En este artículo analizaremos el uso correcto de yield return con ejemplos reales, exploraremos su funcionamiento interno y descubriremos cuándo usarlo y cuándo es mejor mantenerse alejado. ¡Allá vamos!

\n\n

¿Qué es yield return y cómo funciona?

\n\n

Si lo explicamos de forma sencilla, yield return es una forma de decirle al compilador: "Oye, no quiero devolver toda la colección de una vez. Mejor iré entregando los elementos uno por uno, según se necesiten". Este enfoque se llama evaluación perezosa (lazy evaluation).

\n\n

Así se ve un ejemplo clásico:

\n\n
public IEnumerable<int> GetNumbers()\n{\n    yield return 1;\n    yield return 2;\n    yield return 3;\n}
\n\n

Al llamar a este método, no obtienes un arreglo [1, 2, 3]. En su lugar, obtienes un iterador que irá entregando los números uno por uno, cuando se los pidas. Cada llamada a MoveNext() avanza la ejecución del método hasta el siguiente yield return.

\n\n

Esto es como una línea de ensamblaje: los elementos se producen solo cuando el consumidor los necesita. Sin copias innecesarias, sin listas gigantescas en memoria, solo trabajo limpio y eficiente.

\n\n

¿Por qué yield return no es simplemente "devolver una lista"?

\n\n

Muchos principiantes piensan: "¿Para qué necesito yield return si puedo simplemente crear un List y devolverlo?". Analicemos esto con un ejemplo concreto.

\n\n

Imagina que necesitas obtener los primeros 10 números pares de una secuencia infinita. Con yield return se hace de manera elegante:

\n\n
public IEnumerable<int> GetEvenNumbers()\n{\n    int i = 0;\n    while (true)\n    {\n        yield return i;\n        i += 2;\n    }\n}\n\n// Uso\nvar firstTenEven = GetEvenNumbers().Take(10).ToList();
\n\n

Intenta hacer lo mismo con List<int> — o entrarás en un bucle infinito, o tendrás que almacenar todos los números generados en memoria. Yield return nos da la capacidad de trabajar con secuencias potencialmente infinitas sin saturar la memoria RAM.

\n\n

Ejemplo práctico: lectura de un archivo grande

\n\n

Volvamos a nuestro archivo de registro de un millón de líneas. Así es como suelen escribir los principiantes:

\n\n
public List<string> ReadLogLines(string path)\n{\n    var lines = new List<string>();\n    using (var reader = new StreamReader(path))\n    {\n        string line;\n        while ((line = reader.ReadLine()) != null)\n        {\n            lines.Add(line);\n        }\n    }\n    return lines;\n}
\n\n

El problema: todo el archivo se carga en memoria. Si el archivo pesa 500 MB, la lista pesará aproximadamente lo mismo. ¿Y si solo necesitas filtrar las líneas con errores? Igual cargarás todo.

\n\n

Aquí está el uso correcto de yield return:

\n\n
public IEnumerable<string> ReadLogLines(string path)\n{\n    using (var reader = new StreamReader(path))\n    {\n        string line;\n        while ((line = reader.ReadLine()) != null)\n        {\n            yield return line;\n        }\n    }\n}\n\n// Filtrado sin cargar todo el archivo\nvar errorLines = ReadLogLines("log.txt")\n    .Where(line => line.Contains("ERROR"))\n    .Take(100);                

Blogs

Book Recommendations