Yield (Instrucción) (Visual Basic)

Envía el siguiente elemento de una colección a una instrucción For Each...Next.

Sintaxis

Yield expression  

Parámetros

Término Definición
expression Obligatorio. Una expresión que se puede convertir implícitamente en el tipo de la función de iterador o el descriptor de acceso Get que contiene la instrucción Yield.

Comentarios

La instrucción Yield devuelve los elementos de una colección de uno en uno. La instrucción Yield se incluye en una función de iterador o en un descriptor de acceso Get, que realiza iteraciones personalizadas en una colección.

Puede consumir una función de iterador mediante una instrucción For Each...Next o una consulta LINQ. Cada iteración del bucle For Each llama a la función de iterador. Cuando se accede a una instrucción Yield en la función de iterador, se devuelve expression y se conserva la ubicación actual que hay en el código. La ejecución se reinicia desde esa ubicación la próxima vez que se llama a la función del iterador.

Debe existir una conversión implícita del tipo de expression en la instrucción Yield al tipo de valor devuelto del iterador.

Para finalizar la iteración se puede usar una instrucción Exit Function o Return.

"Yield" no es una palabra reservada y tiene un significado especial solo cuando se usa en una función Iterator o un descriptor de acceso Get.

Para más información sobre las funciones de iterador y los descriptores de acceso Get, consulte Iteradores.

Funciones de iterador y descriptores de acceso Get

La declaración de una función de o un descriptor de acceso Get debe cumplir los siguientes requisitos:

Una función de iterador no puede aparecer en un evento, un constructor de instancia, un constructor estático o un destructor estático.

Una función de iterador puede ser una función anónima. Para más información, consulta Iteradores.

Control de excepciones.

Una instrucción Yield puede estar dentro de un bloque Try de una instrucción Try...Catch...Finally. Un bloque Try que tiene una instrucción Yield puede tener bloques Catch y puede tener un bloque Finally.

Una instrucción Yield no puede estar dentro de un bloque Catch o un bloque Finally.

Si el cuerpo de For Each (fuera de la función de iterador) produce una excepción, no se ejecuta un bloque Catch en la función de iterador, pero se ejecuta un bloque Finally en la función de iterador. Un bloque Catch dentro de una función de iterador detecta solo las excepciones que se producen dentro de la función de iterador.

Implementación técnica

El siguiente código devuelve un valor IEnumerable (Of String) desde una función de iterador y, después, recorre los elementos de IEnumerable (Of String).

Dim elements As IEnumerable(Of String) = MyIteratorFunction()  
    …  
For Each element As String In elements  
Next  

La llamada a MyIteratorFunction no ejecuta el cuerpo de la función. En su lugar, la llamada devuelve un valor IEnumerable(Of String) en la variable elements.

En una iteración del bucle For Each, se llama al método MoveNext para elements. Esta llamada ejecuta el cuerpo de MyIteratorFunction hasta que se alcanza la siguiente instrucción Yield. La instrucción Yield devuelve una expresión que determina no solo el valor de la variable element para que la utilice el cuerpo del bucle, sino también la propiedad Current de elements, que es un valor IEnumerable (Of String).

En cada iteración subsiguiente del bucle For Each, la ejecución del cuerpo del iterador continúa desde donde se dejó, deteniéndose de nuevo al alcanzar una instrucción Yield. El bucle For Each se completa cuando se alcanza el fin de la función del iterador o una instrucción Return o Exit Function.

Ejemplo 1

El siguiente ejemplo tiene una instrucción Yield que se encuentra dentro de un bucle For…Next. Cada iteración del cuerpo de instrucción For Each en Main crea una llamada a la función de iterador Power. Cada llamada a la función de iterador prosigue con la siguiente ejecución de la instrucción Yield, que se produce durante la siguiente iteración del bucle For…Next.

El tipo de valor devuelto del método iterador es IEnumerable<T>, que es un tipo de interfaz de iterador. Cuando se llama al método iterador, este devuelve un objeto enumerable que contiene las potencias de un número.

Sub Main()
    For Each number In Power(2, 8)
        Console.Write(number & " ")
    Next
    ' Output: 2 4 8 16 32 64 128 256
    Console.ReadKey()
End Sub

Private Iterator Function Power(
ByVal base As Integer, ByVal highExponent As Integer) _
As System.Collections.Generic.IEnumerable(Of Integer)

    Dim result = 1

    For counter = 1 To highExponent
        result = result * base
        Yield result
    Next
End Function

Ejemplo 2

En el ejemplo siguiente se muestra un descriptor de acceso Get que es un iterador. La declaración de la propiedad incluye un modificador Iterator.

Sub Main()
    Dim theGalaxies As New Galaxies
    For Each theGalaxy In theGalaxies.NextGalaxy
        With theGalaxy
            Console.WriteLine(.Name & "  " & .MegaLightYears)
        End With
    Next
    Console.ReadKey()
End Sub

Public Class Galaxies
    Public ReadOnly Iterator Property NextGalaxy _
    As System.Collections.Generic.IEnumerable(Of Galaxy)
        Get
            Yield New Galaxy With {.Name = "Tadpole", .MegaLightYears = 400}
            Yield New Galaxy With {.Name = "Pinwheel", .MegaLightYears = 25}
            Yield New Galaxy With {.Name = "Milky Way", .MegaLightYears = 0}
            Yield New Galaxy With {.Name = "Andromeda", .MegaLightYears = 3}
        End Get
    End Property
End Class

Public Class Galaxy
    Public Property Name As String
    Public Property MegaLightYears As Integer
End Class

Para ver más ejemplos, consulte Iteradores.

Vea también