Saltar al pie de página
Iron Academy Logo
Aprender C#
Aprender C#

Otras categorías

Introducción a Yield en C# - Qué es, cómo se usa y cuándo es útil

Tim Corey
43m 58s

Cuando se encuentra por primera vez la palabra clave yield en C#, puede parecer desconcertante. ¿Cómo funciona exactamente? ¿Cuándo se debe utilizar yield return en lugar de una sentencia return tradicional? Para conseguir una comprensión completa, vamos a recorrer una explicación detallada basada en el excelente tutorial de Tim Corey en YouTube: "Intro to Yield in C# - What it is, how to use it, and when it is useful"

En esta guía, haremos referencia a puntos específicos del vídeo de Tim por marca de tiempo para facilitar la navegación e incluiremos ejemplos prácticos para mostrar cómo yield transforma la forma en que se manejan los flujos de datos, las grandes colecciones y la evaluación perezosa.

Introducción a la palabra clave Yield en C

Tim comienza presentando la palabra clave yield y destacando que a menudo puede resultar confusa para los desarrolladores que se encuentran con ella por primera vez. Explica que la sentencia yield permite a un método detener la ejecución, mantener su estado y continuar desde donde lo dejó en la siguiente llamada. Tim subraya que entender el rendimiento es fundamental para procesar datos de forma eficiente, sobre todo cuando se trata de grandes conjuntos de datos o se implementa una lógica de iteración personalizada.

Configuración de un ejemplo sencillo: Clase Programa y Static Void Main

Para eliminar distracciones, Tim crea una sencilla aplicación de consola en Visual Studio, llamada "YieldDemoApp"

Understanding Yield In Csharp 1 related to Configuración de un ejemplo sencillo: Clase Programa y Static Void Main

Qué hace realmente Yield en C

A continuación, Tim profundiza en la teoría. En el minuto 2:04, describe el comportamiento de yield: En lugar de procesar toda una colección a la vez, la sentencia yield retiene un punto -como meter un pulgar en un libro- para que la ejecución pueda pausarse y reanudarse más tarde.

Este comportamiento es crucial para la ejecución diferida, en la que los valores se generan solo cuando se necesitan, en lugar de precomputar todo por adelantado. La descripción de Tim sienta claramente las bases para comprender cómo funciona el retorno de rendimiento.

Escribir código de demostración

En el método estático void Main de la clase Program, establece mensajes básicos como "Inicio de la aplicación" y "Fin de la aplicación" utilizando Console.WriteLine, lo que ayuda a visualizar el flujo claramente cuando se trabaja con un bucle foreach más adelante.

Este ejemplo de código inicial se centra únicamente en la implementación del rendimiento, sin incluir complejidades de interfaz de usuario.

Creación de la clase PersonModel

Para demostrarlo, Tim crea una clase PersonModel con las propiedades FirstName y LastName y un constructor. Cuando se crea un objeto PersonModel, se imprime un mensaje que indica qué usuario se ha inicializado. Esto ayuda a visualizar cuándo se crean los objetos y cuándo se consumen.

Understanding Yield In Csharp 2 related to Creación de la clase PersonModel

Este sencillo paso de generación de código prepara el terreno para trabajar con iteradores personalizados.

Construyendo la clase DataAccess con un retorno de lista tradicional

En el minuto 5:06, Tim pasa a una clase DataAccess con un método GetPeople que devuelve IEnumerable. Inicialmente, el valor de retorno es una lista poblada con tres instancias PersonModel: Tim Corey, Sue Storm y Jane Smith.

Understanding Yield In Csharp 3 related to Construyendo la clase DataAccess con un retorno de lista tradicional

Este método iterador carga todos los objetos inmediatamente en memoria antes de que comience la iteración - un punto importante que Tim contrasta más adelante con el uso de yield.

Understanding Yield In Csharp 4 related to Construyendo la clase DataAccess con un retorno de lista tradicional

Demostración del uso de memoria con List

Después de ejecutar el bucle foreach, Tim muestra que los tres usuarios se crean antes incluso de que se lea el primer elemento. Esto pone de relieve un problema potencial cuando se trabaja con grandes colecciones o grandes conjuntos de datos: el elevado uso de memoria.

Understanding Yield In Csharp 5 related to Demostración del uso de memoria con List

Tim explica que si tuviéramos, digamos, mil usuarios, habríamos creado mil objetos aunque solo necesitáramos unos pocos, lo que daría lugar a una asignación ineficiente de memoria.

Cambiando a Rendimiento por Ejecución Diferida

En el minuto 10:01, Tim modifica GetPeople para utilizar yield return en lugar de crear una colección temporal (una List). Cada sentencia yield return emite directamente un PersonModel cada vez.

Este código crítico dentro del método permite la evaluación perezosa, donde el siguiente elemento se genera sólo cuando es necesario por el foreach.

Tim también aclara que el tipo de retorno del método debe ser IEnumerable, y que el uso de List anularía el propósito de la ejecución diferida.

Debugging: Cómo el compilador genera código para el rendimiento

Tim utiliza puntos de interrupción para explicar el proceso paso a paso. Muestra que antes de la primera llamada a MoveNext, la secuencia está vacía. Sólo cuando foreach necesita el siguiente valor, el compilador activa el bloque iterador y ejecuta la línea yield return num, que inicializa y devuelve el PersonModel.

Understanding Yield In Csharp 6 related to Debugging: Cómo el compilador genera código para el rendimiento

Tim destaca que el compilador genera máquinas de estado especiales bajo el capó para gestionar la ejecución pausada y reanudada.

Beneficios y eficacia del uso de Yield Return

Tim explica por qué el rendimiento es tan eficaz:

  • Puede buscar un registro cada vez.

  • Puede limitar el número de int que necesita.

  • Se evita cargar toda la colección en la memoria.

  • Se mejora la escalabilidad, especialmente cuando se trabaja con procesamiento de archivos o flujos de datos de gran tamaño.

Mediante el uso de .Take(2) de LINQ, Tim demuestra cómo sólo se inicializan dos objetos a pesar de que existen tres declaraciones de retorno de rendimiento, lo que pone de relieve la ejecución diferida en acción.

Ejemplo práctico: Generador de números primos usando Yield

Tim crea un nuevo método estático IEnumerable GetPrimeNumbers() dentro de una clase Generators. En este bucle infinito, Tim utiliza una función auxiliar IsPrimeNumber(int number) para comprobar la primalidad. Si el número es primo, utiliza yield return number para emitirlo.

Este ejemplo muestra que el rendimiento es fundamental para manejar secuencias infinitas con seguridad.

Sin rendimiento, el código se bloquearía debido al consumo ilimitado de memoria. Sin embargo, al utilizar yield, la ejecución diferida garantiza que los números se generen bajo demanda.

Obtención de números primos con Take()

A continuación, Tim muestra cómo obtener de forma segura sólo un número fijo de números primos:

var primeNumbers = Generators.GetPrimeNumbers().Take(10000);
var primeNumbers = Generators.GetPrimeNumbers().Take(10000);

Este código escrito dentro del void estático Main obtiene eficientemente sólo 10.000 primos.

Dado que el retorno de rendimiento produce números uno a uno, el uso de memoria se mantiene bajo.

Iteración personalizada: Usando GetEnumerator y MoveNext

Tim va más allá y explica cómo controlar la iteración manualmente.

Crea un var iterator = primeNumbers.GetEnumerator(), luego utiliza un bucle for con int i y llama a iterator.MoveNext() para obtener elementos manualmente.

Este enfoque manual permite una iteración personalizada, preguntando por el siguiente valor sólo cuando sea necesario y mostrando que el método se reanuda exactamente desde donde se detuvo por última vez.

Un error común: El uso de ToList() en colecciones cedidas

En el minuto 36:45, Tim advierte: convertir una secuencia yield en una lista con .ToList() provoca una evaluación completa inmediata.

Si llamas a .ToList() en una secuencia infinita, corres el riesgo de que tu aplicación se bloquee.

Tim subraya que el retorno de rendimiento está pensado para la evaluación perezosa, y que llamar a .ToList() rompe este patrón al forzar la materialización completa en memoria.

Al trabajar con métodos LINQ, Tim recomienda ser cauteloso a la hora de introducir .ToList().

Resumen: Por qué Yield es una herramienta potente

Tim concluye insistiendo en que, si bien la palabra clave yield añade una ligera sobrecarga (al mantener una máquina de estados), las ventajas de un menor uso de memoria y de la evaluación perezosa la convierten en una potente herramienta de trabajo:

  • Grandes conjuntos de datos

  • Archivos de gran tamaño

  • Iteradores personalizados

  • Secuencias infinitas

  • Flujos de datos

  • Tratamiento diferido

Sugiere practicar con el rendimiento en diferentes proyectos para desarrollar una comprensión más profunda del rendimiento y evitar errores comunes.

Tim concluye invitando a los espectadores a compartir cómo han utilizado el rendimiento en el código de producción.

Conclusión

Al recorrer el vídeo de Tim Corey, hemos visto las inmensas ventajas que la palabra clave yield aporta a C#. Desde la creación de iteradores personalizados hasta la gestión eficiente de grandes colecciones, yield return permite que los retornos de función sean más inteligentes y eficientes en términos de memoria. Tanto si trabaja con var number, var point, var reader, var connection o grandes conjuntos de datos, el dominio de yield puede elevar drásticamente sus habilidades de codificación en C#.

Si no has explorado antes el uso de yield, ahora es el momento perfecto para practicarlo a través de ejemplos sencillos y comprender mejor cómo funciona el retorno yield dentro del compilador de C#. Echa un vistazo al canal oficial de Tim YouTube Channel para ver más vídeos interesantes.

Hero Worlddot related to Introducción a Yield en C# - Qué es, cómo se usa y cuándo es útil
Hero Affiliate related to Introducción a Yield en C# - Qué es, cómo se usa y cuándo es útil

Gana más compartiendo lo que te gusta

¿Creas contenidos para desarrolladores que trabajan con .NET, C#, Java, Python o Node.js? ¡Convierte tu experiencia en un ingreso extra!

Equipo de soporte de Iron

Estamos disponibles online las 24 horas, 5 días a la semana.
Chat
Email
Llámame