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:
Ele deve incluir um modificador do Iterador.
O tipo de retorno deve ser IEnumerable, IEnumerable<T>, IEnumerator ou IEnumerator<T>.
Ele não pode ter parâmetro
ByRef
.
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 Power
funçã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.