Yield ステートメント (Visual Basic)

コレクションの次の要素を For Each...Next ステートメントに送ります。

構文

Yield expression  

パラメーター

用語 定義
expression 必須です。 Yield ステートメントを含む iterator 関数または Get アクセサーの型に暗黙的に変換可能な式。

Remarks

Yield ステートメントでは、コレクションの要素を一度に 1 つずつ返します。 Yield ステートメントは、コレクションに対してカスタムの反復を実行する iterator 関数または Get アクセサーに含まれます。

iterator 関数を使用するには、For Each...Next ステートメントまたは LINQ クエリを使用します。 For Each ループの各反復は、iterator 関数を呼び出します。 Yield ステートメントが iterator 関数に到達すると、expression が返され、コードの現在の位置が保持されます。 次回、Iterator 関数が呼び出されると、この位置から実行が再開されます。

Yield ステートメント内の expression の型から、iterator の戻り値の型への暗黙的な変換が存在する必要があります。

Exit Function または Return ステートメントを使用すると、反復を終了できます。

"Yield" は予約語ではなく、Iterator 関数または Get アクセサーで使用される場合にのみ特別な意味を持ちます。

iterator 関数と Get アクセサーの詳細については、「反復子」を参照してください。

iterator 関数と Get アクセサー

iterator 関数または Get アクセサーの宣言では、次の要件を満たしている必要があります。

iterator 関数を、イベント、インスタンス コンストラクター、静的コンストラクター、静的デストラクターで指定することはできません。

iterator 関数は、匿名関数にすることができます。 詳細については、「 反復子」を参照してください。

例外処理

Yield ステートメントは Try...Catch...Finally ステートメントTry ブロック内に指定できます。 Yield ステートメントがある Try ブロックには、Catch ブロックと Finally ブロックを記述することができます。

Yield ステートメントを Catch ブロックや Finally ブロックに記述することはできません。

(iterator 関数の外部の) For Each 本体で例外がスローされた場合、iterator 関数の Catch ブロックは実行されず、iterator 関数の Finally ブロックが実行されます。 iterator 関数内の Catch ブロックでキャッチされるのは、iterator 関数内で発生した例外だけです。

技術的な実装

次のコードでは、iterator 関数から IEnumerable (Of String) を返した後、IEnumerable (Of String) の要素を反復処理しています。

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

MyIteratorFunction への呼び出しでは、関数の本体は実行されません。 この呼び出しでは、IEnumerable(Of String)elements 変数に返されます。

For Each ループの反復処理では、MoveNext について elements メソッドが呼び出されます。 この呼び出しでは、次の MyIteratorFunction ステートメントに到達するまで、Yield の本体が実行されます。 Yield ステートメントによって、ループ本体で使用するための element 変数の値だけでなく、IEnumerable (Of String) である要素の Current プロパティも判断する式が返されます。

For Each ループの以降の各反復処理では、反復子本体の実行が中断した場所から続行し、Yield ステートメントに到達したときに再度停止します。 iterator 関数または Return または Exit Function ステートメントの最後に到達すると、For Each ループは完了します。

例 1

次の例では、For…Next ループ内に Yield ステートメントが含まれます。 Main 内の For Each ステートメント本体の各反復処理では、Power Iterator 関数が呼び出されます。 Iterator 関数を呼び出すごとに、Yield ステートメントの次の実行に進みます。これは、For…Next ループの次の反復処理で行われます。

Iterator メソッドの戻り値の型は、反復子インターフェイス型の IEnumerable<T> です。 Iterator メソッドが呼び出されると、数値の累乗を含む列挙可能なオブジェクトが返されます。

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

例 2

次の例は、反復子である Get アクセサーを示しています。 プロパティの宣言には、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

その他の例については、「反復子」を参照してください。

関連項目