Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
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 Each
boucle ...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 Each
boucle ...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 utiliserExit For
à la fin duFinally
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 group
que ces modifications n’affectent pas l’itération de la boucle.
Lorsque tous les éléments de la collection ont été affectés element
successivement, 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 Each
construction ...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 Each
boucle ...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 group
element
. 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 On
sur , 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 Long
Integer
. 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 Each
boucle ...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 Each
boucle ...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 Each
boucle ...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 Each
boucle ...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 ListCars
cars.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