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
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)
Vue d'ensemble des initialiseurs de collections (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. |