Partager via


Pour chaque... Next Statement (Visual Basic)

Répète un groupe d’instructions pour chaque élément d’une collection.

Syntaxe

For Each element [ As datatype ] In group
    [ statements ]
    [ Continue For ]
    [ statements ]
    [ Exit For ]
    [ statements ]
Next [ element ]

Pièces

Terme Définition
element Obligatoire dans l’instruction For Each. Facultatif dans l’instruction Next . Variable. Utilisé pour itérer au sein des éléments de la collection.
datatype Facultatif s’il Option Infer est activé (valeur par défaut) ou element est déjà déclaré ; obligatoire s’il Option Infer est désactivé et element n’est pas déjà déclaré. Type de données de element.
group Obligatoire. Variable avec un type qui est un type de collection ou Object. Fait référence à la collection sur laquelle les statements éléments doivent être répétés.
statements Optionnel. Une ou plusieurs instructions entre For Each et Next qui s’exécutent sur chaque élément dans group.
Continue For Optionnel. Transfère le contrôle au début de la For Each boucle.
Exit For Optionnel. Transfère le contrôle hors de la For Each boucle.
Next Obligatoire. Termine la définition de la For Each boucle.

Exemple simple

Utilisez une For Eachboucle ...Next lorsque vous souhaitez répéter un ensemble d’instructions pour chaque élément d’une collection ou d’un tableau.

Conseil / Astuce

A pour... L’instruction suivante fonctionne bien lorsque vous pouvez associer chaque itération d’une boucle à une variable de contrôle et déterminer les valeurs initiales et finales de cette variable. Toutefois, lorsque vous traitez d’une collection, le concept de valeurs initiales et finales n’est pas significatif, et vous ne savez pas nécessairement combien d’éléments la collection a. Dans ce genre de cas, une For Eachboucle ...Next est souvent un meilleur choix.

Dans l’exemple suivant, le For Each... Next l’instruction itère dans tous les éléments d’une collection List.

' Create a list of strings by using a
' collection initializer.
Dim lst As New List(Of String) _
    From {"abc", "def", "ghi"}

' Iterate through the list.
For Each item As String In lst
    Debug.Write(item & " ")
Next
Debug.WriteLine("")
'Output: abc def ghi

Pour plus d’exemples, consultez Collections et tableaux.

Boucles imbriquées

Vous pouvez imbriquer des boucles For Each en plaçant une boucle à l'intérieur d'une autre.

L’exemple suivant illustre l’imbrication For Each... Next Structures.

' Create lists of numbers and letters
' by using array initializers.
Dim numbers() As Integer = {1, 4, 7}
Dim letters() As String = {"a", "b", "c"}

' Iterate through the list by using nested loops.
For Each number As Integer In numbers
    For Each letter As String In letters
        Debug.Write(number.ToString & letter & " ")
    Next
Next
Debug.WriteLine("")
'Output: 1a 1b 1c 4a 4b 4c 7a 7b 7c

Lorsque vous imbriquez des boucles, chaque boucle doit avoir une variable unique element .

Vous pouvez également imbriquer différents types de structures de contrôle entre elles. Pour plus d’informations, consultez Structures de contrôle imbriquées.

Exit For et Continue For

L’instruction Exit For entraîne la sortie de l’exécution du For... Next boucle et transfère le contrôle à l’instruction qui suit l’instruction Next .

L’instruction transfère immédiatement le contrôle Continue For à l’itération suivante de la boucle. Pour en savoir plus, consultez Instruction Continue.

L’exemple suivant montre comment utiliser les instructions et Exit For les Continue For instructions.

Dim numberSeq() As Integer =
    {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}

For Each number As Integer In numberSeq
    ' If number is between 5 and 8, continue
    ' with the next iteration.
    If number >= 5 And number <= 8 Then
        Continue For
    End If

    ' Display the number.
    Debug.Write(number.ToString & " ")

    ' If number is 10, exit the loop.
    If number = 10 Then
        Exit For
    End If
Next
Debug.WriteLine("")
' Output: 1 2 3 4 9 10

Vous pouvez placer n’importe quel nombre d’instructions Exit For dans une For Each boucle. Lorsqu’elle est utilisée dans des boucles imbriquées For Each , Exit For l’exécution quitte la boucle la plus interne et transfère le contrôle au niveau supérieur suivant d’imbrication.

Exit For est souvent utilisé après une évaluation de certaines conditions, par exemple, dans un If...Then...Else structure. Vous souhaiterez peut-être utiliser Exit For pour les conditions suivantes :

  • Continuer à itérer est inutile ou impossible. Cela peut être dû à une valeur erronée ou à une demande d’arrêt.

  • Une exception est interceptée dans un Try...Catch...Finally. Vous pouvez utiliser Exit For à la fin du Finally bloc.

  • Il y a une boucle infinie, qui est une boucle qui peut exécuter un grand ou même nombre infini de fois. Si vous détectez une telle condition, vous pouvez l’utiliser Exit For pour échapper à la boucle. Pour plus d’informations, consultez Instruction Do...Loop.

Itérateurs

Vous utilisez un itérateur pour effectuer une itération personnalisée sur une collection. Un itérateur peut être une fonction ou un Get accesseur. Il utilise une Yield instruction pour renvoyer chaque élément de la collection un par un.

Vous appelez un itérateur à l’aide d’une For Each...Next instruction. Chaque itération de la For Each boucle appelle l’itérateur. Lorsqu’une Yield instruction est atteinte dans l’itérateur, l’expression de l’instruction Yield est retournée et l’emplacement actuel dans le code est conservé. L’exécution est redémarrée à partir de cet emplacement la prochaine fois que l’itérateur est appelé.

L’exemple suivant utilise une fonction d’itérateur. La fonction itérateur a une Yield instruction qui se trouve à l’intérieur d’un For... Boucle suivante . Dans la ListEvenNumbers méthode, chaque itération du corps de l’instruction For Each crée un appel à la fonction itérateur, qui passe à l’instruction suivante Yield .

Public Sub ListEvenNumbers()
    For Each number As Integer In EvenSequence(5, 18)
        Debug.Write(number & " ")
    Next
    Debug.WriteLine("")
    ' Output: 6 8 10 12 14 16 18
End Sub

Private Iterator Function EvenSequence(
ByVal firstNumber As Integer, ByVal lastNumber As Integer) _
As System.Collections.Generic.IEnumerable(Of Integer)

    ' Yield even numbers in the range.
    For number = firstNumber To lastNumber
        If number Mod 2 = 0 Then
            Yield number
        End If
    Next
End Function

Pour plus d’informations, consultez Itérateurs, Instruction Rendement et Itérateur.

Implémentation technique

Quand un For Each... Next exécutions d’instructions, Visual Basic évalue la collection une seule fois avant le démarrage de la boucle. Si votre instruction bloque les modifications element ou groupque ces modifications n’affectent pas l’itération de la boucle.

Lorsque tous les éléments de la collection ont été affectés elementsuccessivement, la boucle s’arrête et le For Each contrôle passe à l’instruction suivant l’instruction Next .

Si Option Infer est activée (son paramètre par défaut), le compilateur Visual Basic peut déduire le type de données de element. S’il est désactivé et element n’a pas été déclaré en dehors de la boucle, vous devez le déclarer dans l’instruction For Each . Pour déclarer explicitement le type de element données, utilisez une As clause. Sauf si le type de données de l’élément est défini en dehors de la For Eachconstruction ...Next , son étendue est le corps de la boucle. Notez que vous ne pouvez pas déclarer element à la fois en dehors et à l’intérieur de la boucle.

Vous pouvez éventuellement spécifier element dans l’instruction Next . Cela améliore la lisibilité de votre programme, en particulier si vous avez des boucles imbriquées For Each . Vous devez spécifier la même variable que celle qui apparaît dans l’instruction correspondante For Each .

Vous pouvez éviter de modifier la valeur d’une element boucle. Cela peut rendre plus difficile la lecture et le débogage de votre code. La modification de la valeur de n’affecte pas la collection ou ses éléments, qui ont été déterminés lors de group la première entrée de la boucle.

Lorsque vous imbriquez des boucles, si une instruction d’un Next niveau d’imbrication externe est rencontrée avant le Next niveau interne, le compilateur signale une erreur. Toutefois, le compilateur peut détecter cette erreur qui se chevauche uniquement si vous spécifiez element dans chaque Next instruction.

Si votre code dépend de la traversée d’une collection dans un ordre particulier, une For Eachboucle ...Next n’est pas le meilleur choix, sauf si vous connaissez les caractéristiques de l’objet énumérateur que la collection expose. L’ordre de traversée n’est pas déterminé par Visual Basic, mais par la MoveNext méthode de l’objet énumérateur. Par conséquent, vous ne pouvez pas prédire l’élément de la collection qui est le premier à être retourné element, ou qui est le suivant à retourner après un élément donné. Vous pouvez obtenir des résultats plus fiables à l’aide d’une structure de boucle différente, telle que For...Next ou Do...Loop.

Le runtime doit être en mesure de convertir les éléments en groupelement. L’instruction [Option Strict] contrôle si les conversions d’élargissement et de réduction sont autorisées (Option Strict est désactivée, sa valeur par défaut) ou si seules les conversions étendues sont autorisées (Option Strict est activée). Pour plus d’informations, consultez Conversions restrictives.

Le type de données doit être un type de group référence qui fait référence à une collection ou à un tableau énumérable. Cela signifie généralement qu’il group s’agit d’un objet qui implémente l’interface IEnumerable de l’espace System.Collections de noms ou l’interface IEnumerable<T> de l’espace System.Collections.Generic de noms. System.Collections.IEnumerable définit la GetEnumerator méthode, qui retourne un objet d’énumérateur pour la collection. L’objet énumérateur implémente l’interface System.Collections.IEnumerator de l’espace System.Collections de noms et expose la Current propriété et les ResetMoveNext méthodes. Visual Basic les utilise pour parcourir la collection.

conversions restrictives

Quand Option Strict elle est définie Onsur , la réduction des conversions entraîne généralement des erreurs du compilateur. Dans une For Each instruction, toutefois, les conversions des éléments à group utiliser element sont évaluées et effectuées au moment de l’exécution, et les erreurs du compilateur provoquées par des conversions restrictives sont supprimées.

Dans l’exemple suivant, l’affectation de m la valeur initiale pour n laquelle elle n’est pas compilée est Option Strict activée, car la conversion d’un Long vers un Integer est une conversion restrictive. Dans l’instruction For Each , toutefois, aucune erreur du compilateur n’est signalée, même si l’affectation nécessite number la même conversion en LongInteger. Dans l’instruction For Each qui contient un grand nombre, une erreur d’exécution se produit lorsqu’elle ToInteger est appliquée au grand nombre.

Option Strict On

Imports System

Module Program
    Sub Main(args As String())
        ' The assignment of m to n causes a compiler error when 
        ' Option Strict is on.
        Dim m As Long = 987
        'Dim n As Integer = m

        ' The For Each loop requires the same conversion but
        ' causes no errors, even when Option Strict is on.
        For Each number As Integer In New Long() {45, 3, 987}
            Console.Write(number & " ")
        Next
        Console.WriteLine()
        ' Output: 45 3 987

        ' Here a run-time error is raised because 9876543210
        ' is too large for type Integer.
        'For Each number As Integer In New Long() {45, 3, 9876543210}
        '    Console.Write(number & " ")
        'Next
    End Sub
End Module

Appels IEnumerator

Lorsque l’exécution d’une For Eachboucle ...Next démarre, Visual Basic vérifie que cela group fait référence à un objet de collection valide. Si ce n’est pas le cas, elle lève une exception. Sinon, il appelle la MoveNext méthode et la Current propriété de l’objet énumérateur pour retourner le premier élément. Si MoveNext elle indique qu’il n’existe aucun élément suivant, autrement dit, si la collection est vide, la boucle s’arrête et le For Each contrôle passe à l’instruction suivant l’instruction Next . Sinon, Visual Basic définit element le premier élément et exécute le bloc d’instructions.

Chaque fois que Visual Basic rencontre l’instruction Next , elle revient à l’instruction For Each . Là encore, il appelle MoveNext et Current retourne l’élément suivant, puis il exécute à nouveau le bloc ou arrête la boucle en fonction du résultat. Ce processus se poursuit jusqu’à MoveNext ce qu’il n’y ait pas d’élément suivant ou qu’une Exit For instruction soit rencontrée.

Modification de la collection. L’objet énumérateur retourné par GetEnumerator normalement ne vous permet pas de modifier la collection en ajoutant, supprimant, remplaçant ou réorganisant les éléments. Si vous modifiez la collection après avoir lancé une For Eachboucle ...Next , l’objet énumérateur devient non valide et la prochaine tentative d’accès à un élément provoque une InvalidOperationException exception.

Toutefois, ce blocage de modification n’est pas déterminé par Visual Basic, mais plutôt par l’implémentation de l’interface IEnumerable . Il est possible d’implémenter IEnumerable de manière à permettre la modification pendant l’itération. Si vous envisagez de procéder à une telle modification dynamique, assurez-vous que vous comprenez les caractéristiques de l’implémentation IEnumerable sur la collection que vous utilisez.

Modification des éléments de collection. La Current propriété de l’objet énumérateur est ReadOnly et retourne une copie locale de chaque élément de collection. Cela signifie que vous ne pouvez pas modifier les éléments eux-mêmes dans une For Eachboucle ...Next Toute modification que vous apportez affecte uniquement la copie locale et Current n’est pas répercutée dans la collection sous-jacente. Toutefois, si un élément est un type de référence, vous pouvez modifier les membres de l’instance vers laquelle il pointe. L’exemple suivant modifie le BackColor membre de chaque thisControl élément. Toutefois, vous ne pouvez pas le modifier thisControl lui-même.

Sub LightBlueBackground(thisForm As System.Windows.Forms.Form)
    For Each thisControl In thisForm.Controls
        thisControl.BackColor = System.Drawing.Color.LightBlue
    Next thisControl
End Sub

L’exemple précédent peut modifier le BackColor membre de chaque thisControl élément, bien qu’il ne puisse pas le modifier thisControl lui-même.

Traversée des tableaux. Étant donné que la Array classe implémente l’interface IEnumerable , tous les tableaux exposent la GetEnumerator méthode. Cela signifie que vous pouvez itérer au sein d’un tableau avec une For Eachboucle ...Next Toutefois, vous ne pouvez lire que les éléments de tableau. Vous ne pouvez pas les modifier.

Exemple 1

L’exemple suivant répertorie tous les dossiers du répertoire C :\ à l’aide de la DirectoryInfo classe.

Dim dInfo As New System.IO.DirectoryInfo("c:\")
For Each dir As System.IO.DirectoryInfo In dInfo.GetDirectories()
    Debug.WriteLine(dir.Name)
Next

Exemple 2

L’exemple suivant illustre une procédure de tri d’une collection. L’exemple trie les instances d’une Car classe qui sont stockées dans un List<T>. La Car classe implémente l’interface IComparable<T> , ce qui nécessite que la CompareTo méthode soit implémentée.

Chaque appel à la méthode effectue une comparaison unique utilisée pour le CompareTo tri. Le code écrit par l’utilisateur dans la CompareTo méthode retourne une valeur pour chaque comparaison de l’objet actuel avec un autre objet. La valeur retournée est inférieure à zéro si l’objet actuel est inférieur à l’autre objet, supérieur à zéro si l’objet actuel est supérieur à l’autre objet et zéro s’il est égal à celui-ci. Cela vous permet de définir dans le code les critères supérieurs, inférieurs et égaux.

Dans la méthode, l’instruction ListCarscars.Sort() trie la liste. Cet appel de la méthode Sort de List<T> provoque automatiquement l'appel de la méthode CompareTo pour les objets Car dans List.

Public Sub ListCars()

    ' Create some new cars.
    Dim cars As New List(Of Car) From
    {
        New Car With {.Name = "car1", .Color = "blue", .Speed = 20},
        New Car With {.Name = "car2", .Color = "red", .Speed = 50},
        New Car With {.Name = "car3", .Color = "green", .Speed = 10},
        New Car With {.Name = "car4", .Color = "blue", .Speed = 50},
        New Car With {.Name = "car5", .Color = "blue", .Speed = 30},
        New Car With {.Name = "car6", .Color = "red", .Speed = 60},
        New Car With {.Name = "car7", .Color = "green", .Speed = 50}
    }

    ' Sort the cars by color alphabetically, and then by speed
    ' in descending order.
    cars.Sort()

    ' View all of the cars.
    For Each thisCar As Car In cars
        Debug.Write(thisCar.Color.PadRight(5) & " ")
        Debug.Write(thisCar.Speed.ToString & " ")
        Debug.Write(thisCar.Name)
        Debug.WriteLine("")
    Next

    ' Output:
    '  blue  50 car4
    '  blue  30 car5
    '  blue  20 car1
    '  green 50 car7
    '  green 10 car3
    '  red   60 car6
    '  red   50 car2
End Sub

Public Class Car
    Implements IComparable(Of Car)

    Public Property Name As String
    Public Property Speed As Integer
    Public Property Color As String

    Public Function CompareTo(ByVal other As Car) As Integer _
        Implements System.IComparable(Of Car).CompareTo
        ' A call to this method makes a single comparison that is
        ' used for sorting.

        ' Determine the relative order of the objects being compared.
        ' Sort by color alphabetically, and then by speed in
        ' descending order.

        ' Compare the colors.
        Dim compare As Integer
        compare = String.Compare(Me.Color, other.Color, True)

        ' If the colors are the same, compare the speeds.
        If compare = 0 Then
            compare = Me.Speed.CompareTo(other.Speed)

            ' Use descending order for speed.
            compare = -compare
        End If

        Return compare
    End Function
End Class

Voir aussi