Instructions d’itération - for
, foreach
, do
et while
Les instructions d’itération exécutent à plusieurs reprises une instruction ou un bloc d’instructions. L’instruction for
exécute son corps tandis qu’une expression booléenne spécifiée donne la valeur true
. L’instruction foreach
énumère les éléments d’une collection et exécute son corps pour chaque élément de la collection. L’instruction do
exécute de manière conditionnelle son corps une ou plusieurs fois. L’instruction while
exécute de manière conditionnelle son corps zéro ou plusieurs fois.
À tout moment dans le corps d’une instruction d’itération, vous pouvez sortir de la boucle à l’aide de l’instruction break
. Vous pouvez passer à l’itération suivante dans la boucle à l’aide de l’instruction continue
.
Instruction for
L’instruction for
exécute une instruction ou un bloc d’instructions tant qu’une expression booléenne donne la valeur true
. L’exemple suivant montre l’instruction for
qui exécute son corps alors qu’un compteur entier est inférieur à trois :
for (int i = 0; i < 3; i++)
{
Console.Write(i);
}
// Output:
// 012
L’exemple précédent montre les éléments de l’instruction for
:
La section initialiseur exécutée une seule fois, avant d’entrer dans la boucle. En règle générale, vous déclarez et initialisez une variable de boucle locale dans cette section. La variable déclarée n’est pas accessible à partir de l’extérieur de l’instruction
for
.La section initialiseur de l’exemple précédent déclare et initialise une variable de compteur entier :
int i = 0
La section condition qui détermine si l’itération suivante de la boucle doit être exécutée. Si elle est évaluée à
true
ou si elle n’est pas présente, l’itération suivante est exécutée ; sinon, la boucle est supprimée. La section condition doit être une expression booléenne.La section condition de l’exemple précédent vérifie si une valeur de compteur est inférieure à trois :
i < 3
La section itérateur définit ce qui se produit après chaque exécution du corps de la boucle.
La section itérateur de l’exemple précédent incrémente le compteur :
i++
Le corps de la boucle, qui doit être une instruction ou un bloc d’instructions.
La section itérateur peut contenir zéro, une ou plusieurs des expressions d’instruction suivantes, séparées par des virgules :
- Expression d’incrémentation préfixée ou suffixée, telle que
++i
oui++
- Expression de décrémentation préfixée ou suffixée, telle que
--i
oui--
- assignation
- Appel d’une méthode
await
, expression- création d’un objet à l’aide de l’opérateur
new
Si vous ne déclarez pas de variable de boucle dans la section initialiseur, vous pouvez également utiliser zéro ou plusieurs expressions de la liste précédente dans la section initialiseur. L’exemple suivant illustre plusieurs utilisations moins courantes des sections initialiseur et itérateur : l’attribution d’une valeur à une variable externe dans la section initialiseur, l’appel d’une méthode dans les sections initialiseur et itérateur, et la modification des valeurs de deux variables dans la section itérateur :
int i;
int j = 3;
for (i = 0, Console.WriteLine($"Start: i={i}, j={j}"); i < j; i++, j--, Console.WriteLine($"Step: i={i}, j={j}"))
{
//...
}
// Output:
// Start: i=0, j=3
// Step: i=1, j=2
// Step: i=2, j=1
Toutes les sections de l’instruction for
sont facultatives. Par exemple, le code suivant définit la boucle for
infinie :
for ( ; ; )
{
//...
}
Instruction foreach
L’instruction foreach
exécute une instruction ou un bloc d’instructions pour chaque élément d’une instance du type qui implémente l’interface System.Collections.IEnumerable ou System.Collections.Generic.IEnumerable<T>, comme l’indique l’exemple suivant :
List<int> fibNumbers = new() { 0, 1, 1, 2, 3, 5, 8, 13 };
foreach (int element in fibNumbers)
{
Console.Write($"{element} ");
}
// Output:
// 0 1 1 2 3 5 8 13
L’instruction foreach
n’est pas limitée à ces types. Vous pouvez l’utiliser avec une instance de n’importe quel type qui répond aux conditions suivantes :
- Un type a la méthode
GetEnumerator
sans paramètre publique. La méthodeGetEnumerator
peut être la méthode d’extension d’un type. - Le type de retour de la méthode
GetEnumerator
contient la propriété publiqueCurrent
et la méthode sans paramètre publiqueMoveNext
, dont le type de retour estbool
.
L’exemple suivant utilise l’instruction foreach
avec une instance de type System.Span<T> qui n’implémente aucune interface :
Span<int> numbers = [3, 14, 15, 92, 6];
foreach (int number in numbers)
{
Console.Write($"{number} ");
}
// Output:
// 3 14 15 92 6
Si la propriété Current
de l’énumérateur retourne une valeur de retour de référence (ref T
où T
est le type de l’élément de collection), vous pouvez déclarer une variable d’itération avec le modificateur ref
ou ref readonly
, comme l’indique l’exemple suivant :
Span<int> storage = stackalloc int[10];
int num = 0;
foreach (ref int item in storage)
{
item = num++;
}
foreach (ref readonly var item in storage)
{
Console.Write($"{item} ");
}
// Output:
// 0 1 2 3 4 5 6 7 8 9
Si la collection source de l’instruction foreach
est vide, le corps de l’instruction foreach
n’est pas exécuté et est ignoré. Si l’instruction foreach
est appliquée à null
, une NullReferenceException est levée.
await foreach
Vous pouvez utiliser l’instruction await foreach
pour consommer un flux asynchrone de données, autrement dit, le type de collection qui implémente l’interface IAsyncEnumerable<T>. Chaque itération de la boucle peut être suspendue pendant que l’élément suivant est récupéré de façon asynchrone. L’exemple suivant montre comment utiliser l’instruction await foreach
:
await foreach (var item in GenerateSequenceAsync())
{
Console.WriteLine(item);
}
Vous pouvez également utiliser l’instruction await foreach
avec une instance de n’importe quel type qui répond aux conditions suivantes :
- Un type a la méthode
GetAsyncEnumerator
sans paramètre public. Cette méthode peut être la méthode d’extension d’un type. - Le type de retour de la méthode
GetAsyncEnumerator
a la propriétéCurrent
publique et la méthodeMoveNextAsync
publique sans paramètre dont le type de retour estTask<bool>
,ValueTask<bool>
ou tout autre type awaitable dont la méthode duGetResult
de l’awaiter retourne une valeurbool
.
Par défaut, les éléments de flux sont traités dans le contexte capturé. Si vous souhaitez désactiver la capture du contexte, utilisez la méthode d’extension TaskAsyncEnumerableExtensions.ConfigureAwait. Pour plus d’informations sur les contextes de synchronisation et la capture du contexte actuel, consultez Utilisation du modèle asynchrone basé sur les tâches. Pour plus d’informations sur les flux asynchrones, consultez le didacticiel sur les flux asynchrones.
Type d’une variable d’itération
Vous pouvez utiliser le mot clévar
pour laisser le compilateur déduire le type d’une variable d’itération dans l’instruction foreach
, comme le montre le code suivant :
foreach (var item in collection) { }
Remarque
Le type de var
peut être déduit par le compilateur en tant que type de référence nullable, selon que le contexte prenant en charge nullable est activé ou que le type d’une expression d’initialisation est un type de référence.
Pour plus d’informations, consultez Variables locales implicitement typées.
Vous pouvez également spécifier explicitement le type d’une variable d’itération, comme le montre le code suivant :
IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }
Dans le formulaire précédent, le type T
d’un élément de collection doit être implicitement ou explicitement convertible en type V
d’une variable d’itération. Si une conversion explicite à partir de T
vers V
échoue à son temps d’exécution, l’instruction foreach
lève une InvalidCastException. Par exemple, si T
est un type de classe non scellé, V
peut être n’importe quel type d’interface, même celui que T
n’implémente pas. Au moment de l’exécution, le type d’un élément de collection peut être celui qui dérive de T
et implémente réellement V
. Si ce n’est pas le cas, une InvalidCastException est levée.
Instruction do
L’instruction do
exécute une instruction ou un bloc d’instructions tant qu’une expression booléenne donne la valeur true
. Dans la mesure où cette expression est évaluée après chaque exécution de la boucle, une boucle do
s’exécute une ou plusieurs fois. La boucle do
diffère de la boucle while
, qui s’exécute zéro ou plusieurs fois.
L’exemple suivant illustre l’utilisation de l’instruction do
:
int n = 0;
do
{
Console.Write(n);
n++;
} while (n < 5);
// Output:
// 01234
Instruction while
L’instruction while
exécute une instruction ou un bloc d’instructions tant qu’une expression booléenne donne la valeur true
. Dans la mesure où cette expression est évaluée avant chaque exécution de la boucle, une boucle while
s’exécute plusieurs fois ou pas du tout. La boucle while
diffère de la boucle do
, qui s’exécute une ou plusieurs fois.
L’exemple suivant illustre l’utilisation de l’instruction while
:
int n = 0;
while (n < 5)
{
Console.Write(n);
n++;
}
// Output:
// 01234
spécification du langage C#
Pour plus d’informations, consultez les sections suivantes de la spécification du langage C# :
Pour plus d’informations sur ces fonctionnalités, consultez les notes de proposition des fonctionnalités suivantes :