Επεξεργασία

Κοινή χρήση μέσω


Yield Statement (Visual Basic)

Sends the next element of a collection to a For Each...Next statement.

Syntax

Yield expression  

Parameters

Term Definition
expression Required. An expression that is implicitly convertible to the type of the iterator function or Get accessor that contains the Yield statement.

Remarks

The Yield statement returns one element of a collection at a time. The Yield statement is included in an iterator function or Get accessor, which perform custom iterations over a collection.

You consume an iterator function by using a For Each...Next Statement or a LINQ query. Each iteration of the For Each loop calls the iterator function. When a Yield statement is reached in the iterator function, expression is returned, and the current location in code is retained. Execution is restarted from that location the next time that the iterator function is called.

An implicit conversion must exist from the type of expression in the Yield statement to the return type of the iterator.

You can use an Exit Function or Return statement to end the iteration.

"Yield" is not a reserved word and has special meaning only when it is used in an Iterator function or Get accessor.

For more information about iterator functions and Get accessors, see Iterators.

Iterator Functions and Get Accessors

The declaration of an iterator function or Get accessor must meet the following requirements:

An iterator function cannot occur in an event, instance constructor, static constructor, or static destructor.

An iterator function can be an anonymous function. For more information, see Iterators.

Exception Handling

A Yield statement can be inside a Try block of a Try...Catch...Finally Statement. A Try block that has a Yield statement can have Catch blocks, and can have a Finally block.

A Yield statement cannot be inside a Catch block or a Finally block.

If the For Each body (outside of the iterator function) throws an exception, a Catch block in the iterator function is not executed, but a Finally block in the iterator function is executed. A Catch block inside an iterator function catches only exceptions that occur inside the iterator function.

Technical Implementation

The following code returns an IEnumerable (Of String) from an iterator function and then iterates through the elements of the IEnumerable (Of String).

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

The call to MyIteratorFunction doesn't execute the body of the function. Instead the call returns an IEnumerable(Of String) into the elements variable.

On an iteration of the For Each loop, the MoveNext method is called for elements. This call executes the body of MyIteratorFunction until the next Yield statement is reached. The Yield statement returns an expression that determines not only the value of the element variable for consumption by the loop body but also the Current property of elements, which is an IEnumerable (Of String).

On each subsequent iteration of the For Each loop, the execution of the iterator body continues from where it left off, again stopping when it reaches a Yield statement. The For Each loop completes when the end of the iterator function or a Return or Exit Function statement is reached.

Example 1

The following example has a Yield statement that is inside a For…Next loop. Each iteration of the For Each statement body in Main creates a call to the Power iterator function. Each call to the iterator function proceeds to the next execution of the Yield statement, which occurs during the next iteration of the For…Next loop.

The return type of the iterator method is IEnumerable<T>, an iterator interface type. When the iterator method is called, it returns an enumerable object that contains the powers of a number.

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

Example 2

The following example demonstrates a Get accessor that is an iterator. The property declaration includes an Iterator modifier.

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

For additional examples, see Iterators.

See also