Share 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 ]

Éléments

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

Obligatoire. Variable objet. Fait référence à la collection sur laquelle les statements doivent être répétées.

statements

Facultatif. Une ou plusieurs instructions entre For Each et Next qui s'exécutent sur chaque élément dans group.

Continue For

Facultatif. Transfère le contrôle au démarrage de la boucle For Each.

Exit For

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

Next

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

Notes

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.

Visual Basic évalue la collection une seule fois, avant le début de la boucle. Si votre bloc d'instructions modifie 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 la variable element n'a pas été déclarée à l'extérieur de cette boucle, vous devez la déclarer dans l'instruction 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. La modification de la valeur de group n'affecte pas la collection ou ses éléments qui étaient déterminés lorsque la boucle était entrée en premier lieu.

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 gérez une collection, le concept de valeurs initiales et finales n'a pas de sens et vous n'êtes pas obligé de connaître le nombre d'éléments que contient la collection. Dans ce cas, une boucle For Each...Next est un meilleur choix.

Si votre code dépend du parcours d'une collection selon un ordre défini, une boucle For Each...Next ne représente pas le meilleur choix, sauf si vous connaissez les caractéristiques de l'objet énumérateur exposé par la collection. L'ordre de parcours n'est pas déterminé par Visual Basic, mais par la méthode MoveNext de l'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..

Imbrication de boucles

Vous pouvez imbriquer les boucles For Each en plaçant une boucle à l'intérieur d'une autre. Toutefois, chaque boucle doit posséder une variable element unique.

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).

Si une instruction Next d'un niveau d'imbrication externe est rencontrée avant le 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.

Exit For

L'instruction Exit For quitte la boucle For…Next et transfère le contrôle à l'instruction suivant l'instruction Next.

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).

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).

Types de données

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 de group doit être un type référence qui fait référence à une collection ou à un tableau é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<T> 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.

Les éléments de group sont généralement de type Object, mais ils peuvent avoir n'importe quel type de données exécutable.

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'affectation de m comme valeur initiale pour n ne se compile pas lorsque Option Strict est activé parce que la conversion d'un Long en 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.

Modifications

Modification de la collection. L'objet énumérateur retourné par GetEnumerator ne vous permet normalement pas de modifier la collection par l'ajout, la suppression, le remplacement ou la réorganisation d'éléments. 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é parVisual Basic, mais plutôt par l'implémentation de l'interface 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 effectuée n'a d'incidence que sur la copie locale basée sur Current et n'est pas répercutée 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 illustre ce comportement.

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. Pour une illustration, consultez Comment : exécuter plusieurs instructions pour chaque élément dans une collection ou un tableau (Visual Basic).

Exemple

L'exemple suivant montre comment utiliser l'instruction For Each…Next.

' 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

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 

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

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 montre comment trier une collection à l'aide de l'interface IComparable.

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
        ' Determine the relative order of the objects being compared.
        ' This is used to 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

L'exemple suivant inclut une classe de collection personnalisée qui possède un énumérateur personnalisé.

Public Sub ListColors()
    Dim colors As New AllColors()

    For Each theColor As Color In colors
        Debug.Write(theColor.Name & " ")
    Next
    Debug.WriteLine("")
    ' Output: red blue green
End Sub

' Collection class.
Public Class AllColors
    Implements System.Collections.IEnumerable

    Private _colors() As Color =
    {
        New Color With {.Name = "red"},
        New Color With {.Name = "blue"},
        New Color With {.Name = "green"}
    }

    Public Function GetEnumerator() As System.Collections.IEnumerator _
        Implements System.Collections.IEnumerable.GetEnumerator

        Return New ColorEnumerator(_colors)

        ' Instead of creating a using a custom enumerator, you could
        ' use the GetEnumerator of the array.
        'Return _colors.GetEnumerator
    End Function

    ' Custom enumerator.
    Private Class ColorEnumerator
        Implements System.Collections.IEnumerator

        Private _colors() As Color
        Private _position As Integer = -1

        Public Sub New(ByVal colors() As Color)
            _colors = colors
        End Sub

        Public ReadOnly Property Current() As Object Implements System.Collections.IEnumerator.Current
            Get
                Return _colors(_position)
            End Get
        End Property

        Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
            _position += 1
            Return (_position < _colors.Length)
        End Function

        Public Sub Reset() Implements System.Collections.IEnumerator.Reset
            _position = -1
        End Sub
    End Class
End Class

' Element class.
Public Class Color
    Public Property Name As String
End Class

Voir aussi

Tâches

Comment : exécuter plusieurs instructions pour chaque élément dans une collection ou un tableau (Visual Basic)

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)

Collections en Visual Basic

Conversions étendues et restrictives (Visual Basic)

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

Vue d'ensemble des initialiseurs de collections (Visual Basic)

Tableaux dans Visual Basic

Historique des modifications

Date

Historique

Motif

Décembre 2010

Réorganisation de la section Remarques et ajout d'exemples.

Améliorations apportées aux informations.