Partager via


For Each...Next, instruction (Visual Basic)

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

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

Composants

Terme

Définition

element

Requis dans l'instruction For Each. Facultatif dans les instructions Next. Variable. Utilisée pour itérer au sein des éléments de la collection.

datatype

Obligatoire si element n'est pas déjà déclaré. Type de données de element.

group

Requis. Une variable avec un type qui est un type de collection ou un objet. Fait référence à la collection sur laquelle les statements doivent être répétées.

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émarrage de la boucle For Each.

Exit For

Optionnel. Transfert le contrôle hors de la boucle For Each.

Next

Requis. Termine la définition de la boucle For Each.

Exemple simple

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

Conseil

Une For...Next, instruction (Visual Basic) fonctionne correctement lorsque vous pouvez associer chaque itération d'une boucle à une variable de contrôle et déterminer les valeurs initiale et finale de cette variable.Toutefois, lorsque vous utilisez une collection, le concept des valeurs initiales et dernières n'est pas explicite, et vous ne connaissez pas nécessairement le nombre d'éléments que la collection est.Dans ce type de cas, une boucle d' For Each…Next est souvent préférable d'utiliser.

Dans l'exemple suivant, l'instruction d' For Each…Next itère au sein de tous les éléments d'une collection de listes.

' 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 obtenir d'autres exemples, consultez Collections (C# et Visual Basic) et Tableaux dans Visual Basic.

Boucles imbriquées

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

L'exemple suivant illustre des structures For Each…Next imbriquées.

' 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 emboîtez des boucles, chaque boucle doit avoir une seule variable d' element .

Vous pouvez également imbriquer divers types de structures de contrôle l'un dans l'autre. Pour plus d'informations, consultez Structures de contrôle imbriquées (Visual Basic).

Quittez pour & continuer pour

L'instruction d' Quittez pour fait de quitter l'exécution de la boucle et transfère le contrôle d' For…Next à l'instruction qui suit l'instruction d' Next .

L'instruction Continue For transfère immédiatement le contrôle vers l'itération suivante de la boucle. Pour plus d'informations, consultez Continue, instruction (Visual Basic).

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

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 7, 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 boucle For Each. Utilisée dans des boucles For Each imbriquées, l'instruction Exit For quitte la boucle la plus profonde et transfère le contrôle au niveau d'imbrication supérieur suivant.

Exit For est souvent utilisé après l'évaluation d'une condition, par exemple dans une structure If...Then...Else. Vous pouvez utiliser Exit For pour les conditions suivantes :

  • La poursuite de l'itération est inutile ou impossible. Cela peut être causé par une valeur erronée ou une demande d'arrêt.

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

  • Il existe une boucle sans fin, c'est-à-dire une boucle qui pourrait s'exécuter de nombreuses fois, voire indéfiniment. Si vous détectez une telle condition, vous pouvez utiliser Exit For pour abandonner la boucle. Pour plus d'informations, consultez Do...Loop, instruction (Visual Basic).

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 utilisateur d' Get . Il utilise une instruction d' Yield pour retourner chaque élément de la collection un par un.

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

L'exemple suivant utilise une fonction d'itérateur. La fonction d'itérateur a une instruction d' Yield qui est à l'intérieur d'une boucle d' For… next . Dans la méthode d' ListEvenNumbers, chaque itération du corps d'instruction d' For Each crée un appel à la fonction d'itérateur, qui continue à l'instruction d' 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 (C# et Visual Basic), yield, instruction (Visual Basic) et Itérateur (Visual Basic).

Implémentation technique

Lorsqu'une instruction d' For Each…Next s'exécute, Visual Basic prend la collection uniquement une fois, avant la boucle démarre. Si votre bloc d'instructions change element ou group, ces modifications n'affectent pas l'itération de la boucle.

Lorsque tous les éléments de la collection ont été successivement assignés à element, la boucle For Each s'arrête et le contrôle est passé à l'instruction suivant l'instruction Next.

Si element n'a pas été déclaré en dehors de la boucle, vous devez la déclarer dans l'instruction d' For Each . Vous pouvez déclarer explicitement le type d'element en utilisant une instruction As ou vous pouvez compter sur l'inférence de type pour assigner le type. Dans les deux cas, la portée de element est le corps de la boucle. Cependant, vous ne pouvez pas déclarer element à la fois à l'extérieur et à l'intérieur de la boucle.

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

Vous pouvez éviter de changer la valeur de element à l'intérieur d'une boucle. Cette opération rendra la lecture et le débogage de votre code plus difficiles. Modifier la valeur d' group n'affecte pas la collection ou ses éléments, qui étaient déterminés lorsque la boucle a été écrite la première fois.

Lorsque vous avez des boucles d'imbrication, si une instruction d' Next d'un niveau d'imbrication externe est produit avant qu' Next d'un niveau interne, le compilateur signale une erreur. Toutefois, le compilateur peut détecter cette erreur de chevauchement uniquement si vous spécifiez element dans chaque instruction Next.

Si votre code dépend de parcourir une collection dans un ordre particulier, une boucle d' For Each…Next n'est pas le meilleur choix, à moins que vous connaissiez les caractéristiques de l'objet énumérateur que la collection expose. L'ordre de parcours n'est pas déterminé par Visual Basic, mais par la méthode d' MoveNext d'objet énumérateur. Ceci signifie que vous ne pourrez peut-être pas prévoir quel sera le premier élément de la collection retourné dans element ou quel sera l'élément suivant renvoyé après un élément donné. Vous pouvez obtenir des résultats plus fiables à l'aide d'une structure de boucle différente, par exemple For...Next ou Do...Loop..

Le type de données des éléments de group doit pouvoir être converti en type de données de element.

Le type de données d' group doit être un type référence qui fait référence à une collection ou un tableau qui est énumérable. La plupart du temps, cela signifie que group fait référence à un objet qui implémente l'interface IEnumerable de l'espace de noms System.Collections ou l'interface IEnumerable de l'espace de noms System.Collections.Generic. System.Collections.IEnumerable définit la méthode GetEnumerator, qui retourne un objet énumérateur pour la collection. L'objet énumérateur implémente l'interface System.Collections.IEnumerator de l'espace de noms System.Collections et expose la propriété Current et les méthodes Reset et MoveNext. Visual Basic les utilise pour parcourir la collection.

Conversions restrictives

Lorsque Option Strict a la valeur On, les conversions restrictives provoquent ordinairement des erreurs du compilateur. Dans une instruction For Each, cependant, les conversions à partir des éléments de group vers element sont évaluées et exécutées au moment de l'exécution, et les erreurs du compilateur causées par des conversions restrictives sont supprimées.

Dans l'exemple suivant, l'assignation d' m comme valeur initiale pour n ne compile pas lorsque Option Strict est activé parce que la conversion d' Long à Integer est une conversion restrictive. Toutefois, dans l'instruction For Each, aucune erreur de compilateur n'est signalée, même si l'affectation à number nécessite la même conversion de Long à Integer. Dans l'instruction For Each qui contient un nombre élevé, une erreur d'exécution se produit lorsque ToInteger est appliqué au nombre élevé.

Option Strict On 

Module Module1
    Sub Main()
        ' 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

        Console.ReadKey()
    End Sub 
End Module

Appels IEnumerator

Lorsque l'exécution d'une boucle For Each...Next commence, Visual Basic vérifie que group fait référence à un objet de collection valide. Si tel n'est pas le cas, il lève une exception. Sinon, il appelle la méthode MoveNext et la propriété Current de l'objet énumérateur pour retourner le premier élément. Si MoveNext indique qu'il n'y a aucun élément suivant, c'est-à-dire si la collection est vide, la boucle For Each s'arrête et le contrôle est passé à l'instruction qui suit l'instruction Next. Sinon, Visual Basic affecte element au premier élément et exécute le bloc d'instructions.

Chaque fois que Visual Basic rencontre l'instruction Next, il retourne à l'instruction For Each. Il appelle de nouveau MoveNext et Current pour retourner l'élément suivant et exécute à nouveau le bloc ou arrête la boucle selon le résultat. Ce processus continue jusqu'à ce que MoveNext indique qu'il n'y a aucun élément suivant ou qu'une instruction Exit For soit rencontrée.

Modification de la collection. L'énumérateur objet retourné par GetEnumerator normalement ne vous permet pas de modifier la collection n'en ajoutant, en supprimant, en substituant, ou en principale de nouveau aucun élément. Si vous modifiez la collection après avoir lancé une boucle For Each...Next, l'objet énumérateur devient non valide et la tentative d'accès suivante à un élément provoque une exception InvalidOperationException.

Toutefois, ce blocage de modification n'est pas déterminé par Visual Basic, mais plutôt par l'implémentation de l'interface d' IEnumerable . Il est possible d'implémenter IEnumerable de sorte que les modifications soient autorisées pendant l'itération. Si vous comptez effectuer des modifications dynamiques de ce type, soyez sûr que vous connaissez les caractéristiques de l'implémentation de IEnumerable sur la collection que vous utilisez.

Modification d'éléments de collection. La propriété Current de l'objet énumérateur est ReadOnly (Visual Basic). Elle retourne une copie locale de chaque élément de la collection. Cela signifie que vous ne pouvez pas modifier les éléments d'une boucle For Each...Next. Toute modification vous effectuez à affecte uniquement la copie locale d' Current et n'êtes pas répercutée dans le dans la collection sous-jacente. Cependant, si un élément correspond à un type référence, vous pouvez modifier les membres de l'instance vers laquelle il pointe. L'exemple suivant modifie le membre d' BackColor de chaque élément d' thisControl . Vous ne pouvez pas, toutefois, la modification thisControl lui-même.

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

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

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

Exemple

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

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

L'exemple suivant affiche une procédure pour trier une collection. L'exemple trie les instances d'une classe d' Car stockées dans List. La classe Car implémente l'interface IComparable , qui exige que la méthode CompareTo soit implémentée.

Chaque appel à la méthode d' CompareTo effectue une comparaison unique utilisée pour trier. Le code écrit par l'utilisateur dans la méthode CompareTo retourne une valeur pour chaque comparaison de l'objet en cours par un autre objet. La valeur retournée est inférieur à 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'ils sont égaux. Cela vous permet de définir dans le code les critères pour supérieur, inférieur à, et égal.

Dans la méthode ListCars , l'instruction cars.Sort() trie la liste. Cet appel à la méthode Sort de List entraîne l'appel de la méthode CompareTo automatiquement pour les objets de type 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

Référence

For...Next, instruction (Visual Basic)

While...End While, instruction (Visual Basic)

Do...Loop, instruction (Visual Basic)

Concepts

Structures de boucle (Visual Basic)

Conversions étendues et restrictives (Visual Basic)

Initialiseurs d'objets : types nommés et anonymes (Visual Basic)

Initialiseurs de collections (Visual Basic)

Autres ressources

Collections (C# et Visual Basic)

Tableaux dans Visual Basic