Instrução Yield (Visual Basic)

Envia o próximo elemento de uma coleção para uma instrução For Each...Next.

Sintaxe

Yield expression  

Parâmetros

Termo Definição
expression Obrigatórios. Uma expressão implicitamente conversível para o tipo da função iteradora ou acessador Get que contém a instrução Yield.

Comentários

A instrução Yield retorna um elemento de uma coleção por vez. A instrução Yield é incluída em uma função iteradora ou acessador Get, que executa iterações personalizadas em uma coleção.

Você consome uma função iteradora usando um Instrução For Each...Next ou uma consulta LINQ. Cada iteração do loop For Each chama a função iteradora. Quando uma instrução Yield é alcançada na função iteradora, expression é retornado e o local atual no código é mantido. A execução será reiniciada desse local na próxima vez que a função iteradora for chamada.

Uma conversão implícita deve existir do tipo de expression na instrução Yield para o tipo de retorno do iterador.

Você pode usar uma instrução Exit Function ou Return para terminar a iteração.

"Yield" não é uma palavra reservada e tem um significado especial somente quando é usado em uma função Iterator ou acessador Get.

Para obter mais informações sobre funções iteradoras e acessadores Get, confira Iteradores.

Funções iteradoras e obter acessadores

A declaração de uma função iteradora ou acessador Get deve atender aos seguintes requisitos:

Uma função iteradora não pode ocorrer em um evento, construtor de instância, construtor estático ou destruidor estático.

Uma função iteradora pode ser uma função anônima. Para obter mais informações, consulte Iteradores.

Tratamento de exceção

Uma instrução Yield pode estar dentro de um bloco Try de uma Instrução Try...Catch...Finally. Um bloco Try que tem uma instrução Yield pode ter blocos Catch e pode ter um bloco Finally.

Uma instrução Yield não pode estar dentro de um bloco Catch ou bloco Finally.

Se o corpo For Each (fora da função iteradora) lançar uma exceção, um bloco Catch na função iteradora não será executado, mas um bloco Finally na função iteradora será executado. Um bloco Catch dentro de uma função iteradora captura apenas exceções que ocorrem dentro da função iteradora.

Implementação Técnica

O código a seguir retorna um IEnumerable (Of String) de uma função iteradora e, em seguida, itera pelos elementos do IEnumerable (Of String).

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

A chamada a MyIteratorFunction não executa o corpo da função. Em vez disso, a chamada retorna IEnumerable(Of String) na variável elements.

Em uma iteração do loop For Each, o método MoveNext é chamado para elements. Essa chamada executará o corpo de MyIteratorFunction até que a próxima instrução Yield seja atingida. A instrução Yield retorna uma expressão que determina não apenas o valor da variável element para consumo pelo corpo do loop, mas também a propriedade Current dos elementos, que é um IEnumerable (Of String).

Em cada iteração subsequente do loop For Each, a execução do corpo do iterador continuará de onde parou, parando novamente quando atingir uma instrução Yield. O loop For Each é concluído quando o final da função do iterador ou uma instrução Return ou Exit Function é atingida.

Exemplo 1

O exemplo a seguir tem uma instrução Yield que está dentro de um loop For…Next. Cada iteração do corpo da instrução For Each em Main cria uma chamada para a Powerfunção de iterador. Cada chamada à função iteradora prossegue para a próxima execução da instrução Yield que ocorre durante a próxima iteração do loop For…Next.

O tipo de retorno do método iterador é IEnumerable<T>, um tipo de interface de iterador. Quando o método iterador é chamado, ele retorna um objeto enumerável que contém as potências de um 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

Exemplo 2

O exemplo a seguir demonstra um acessador Get que é um iterador. A declaração de propriedade inclui um 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 obter mais exemplos adicionais, consulte Iteradores.

Confira também