Menu

Boucle for en C# : syntaxe, compte à rebours, boucles imbriquées et pièges

Comment fonctionne la boucle for en C# : l'initialiseur, la condition et l'itérateur, compter à rebours et avancer par pas, plusieurs variables de boucle, parcourir un tableau par index, les boucles imbriquées, for(;;), et les bugs de décalage d'un cran et de suppression pendant l'itération.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Une boucle for répète un bloc tant qu'une condition est vraie, avec la préparation et le pas écrits dans l'en-tête de la boucle. C'est la boucle à utiliser quand on compte : un nombre fixe de répétitions, ou chaque index d'un tableau.

Sortie :

Lap 1 of 5
Lap 2 of 5
Lap 3 of 5
Lap 4 of 5
Lap 5 of 5

Comment s'exécutent les trois parties

for (initializer; condition; iterator) s'exécute dans un ordre fixe :

  1. L'initialiseur (int i = 1) s'exécute une fois, avant tout le reste.
  2. La condition (i <= 5) est vérifiée. Si elle est fausse, la boucle se termine et le corps ne s'exécute plus.
  3. Le corps s'exécute.
  4. L'itérateur (i++) s'exécute, puis le contrôle revient à l'étape 2.

Comme la condition est vérifiée avant chaque itération, une boucle for peut s'exécuter zéro fois : for (int i = 10; i < 5; i++) n'entre jamais dans son corps. La boucle ci-dessus se comporte comme cette boucle while :

int i = 1;
while (i <= 5)
{
    Console.WriteLine($"Lap {i} of 5");
    i++;
}

Les deux formes diffèrent sur un détail : continue dans le corps d'un for exécute quand même l'itérateur, alors que dans cette version while il sauterait i++, si bien que la boucle testerait à nouveau le même i et pourrait tourner indéfiniment. Une variable déclarée dans l'initialiseur n'existe qu'à l'intérieur de la boucle. Si vous avez besoin de sa valeur finale ensuite, déclarez-la avant la boucle : int i; for (i = 0; ...; i++) { }.

Compter à rebours et avancer par pas

L'itérateur peut être n'importe quelle expression. Décrémentez pour compter à rebours, ajoutez plus de un pour avancer par pas, ou multipliez pour une suite géométrique :

Sortie :

3... 2... 1... liftoff
 00 15 30 45
 1 10 100 1000

Assurez-vous que l'itérateur rapproche la condition de la valeur fausse. for (int i = 0; i < 10; i--) s'éloigne de 10 et ne s'arrête que lorsque i boucle après deux milliards d'itérations.

Parcourir un tableau par index

Les tableaux exposent Length, les listes Count, et les index valides vont de 0 à cette valeur moins un. L'index vous donne ce que foreach ne donne pas : l'accès à la position, aux voisins, et le droit d'écrire dans le tableau.

Sortie :

#1: 17.99
#2: 4.50
#3: 38.25
#4: 7.43
item 1 vs item 0: down
item 2 vs item 1: up
item 3 vs item 2: down

La dernière boucle commence à 1 parce qu'elle compare chaque élément au précédent. La page sur les tableaux couvre la création, le tri et la copie des tableaux eux-mêmes.

Plusieurs variables de boucle

L'initialiseur peut déclarer plusieurs variables du même type, et l'itérateur peut en mettre plusieurs à jour, séparées par des virgules. L'usage classique est deux index qui avancent l'un vers l'autre :

Sortie :

racecar is a palindrome: True
9, 1, 8, 3

Les deux variables doivent partager un seul type dans une même déclaration : int left = 0, right = 10 fonctionne, int i = 0, string s = "" non.

Boucles imbriquées

Une boucle dans une boucle parcourt toute sa plage une fois par itération de la boucle externe. Les tableaux à deux dimensions et les grilles sont le cas typique :

Sortie :

   1   2   3   4
   2   4   6   8
   3   6   9  12
   4   8  12  16

Le corps interne s'exécute 16 fois (4 × 4). L'imbrication multiplie vite le travail : deux boucles imbriquées sur 10 000 éléments chacune font 100 millions d'itérations. Un break dans la boucle interne ne quitte que la boucle interne ; la page sur break et continue montre comment quitter les deux.

Boucles infinies : for(;;)

Les trois parties de l'en-tête sont facultatives. Sans condition, la boucle tourne jusqu'à ce que quelque chose à l'intérieur la quitte :

Sortie :

Month 1: 70 left
Month 2: 40 left
Month 3: 10 left
Overdrawn in month 4: -20

for (;;) et while (true) se compilent de la même façon ; choisissez celle qu'utilise votre base de code.

Les erreurs de décalage d'un cran

Le bug de for le plus courant est une condition qui va un pas trop loin :

Sortie :

Ada
Grace
Linus
IndexOutOfRangeException at index 3

Un tableau de 3 éléments a les index 0, 1 et 2, donc i < names.Length est la bonne condition. Le bug symétrique consiste à compter à rebours avec i > 0, qui ne visite jamais l'index 0. Sur une List<T>, la même erreur lève ArgumentOutOfRangeException à la place.

Supprimer des éléments pendant la boucle

Supprimer d'une List<T> dans une boucle qui avance décale d'une position vers le bas chaque élément suivant, si bien que la boucle saute l'élément situé juste après chaque suppression :

Sortie :

forward:  5, 0, 3, 7
backward: 5, 3, 7

La boucle vers l'avant a laissé un 0 : après la suppression de l'index 1, le second zéro est passé à l'index 1, mais i++ était déjà passé à l'index 2. Parcourir à l'envers évite le problème, car les suppressions ne décalent que des éléments déjà visités. Comme alternative en une ligne, stock.RemoveAll(x => x == 0) fait la même chose. Une boucle foreach n'autorise pas du tout la suppression ; elle lève InvalidOperationException.

Compteurs à virgule flottante

Évitez les compteurs de boucle double testés par égalité. 0.1 n'a pas de représentation binaire exacte, donc l'ajouter dix fois ne donne pas exactement 1.0 :

for (double x = 0; x != 1.0; x += 0.1)   // never ends: x skips past 1.0
{
}

Comptez plutôt avec un entier et calculez la valeur à partir de lui : for (int i = 0; i <= 10; i++) { double x = i / 10.0; }.

for ou foreach

BesoinUtiliser
Lire chaque élément dans l'ordreforeach
L'index, ou les voisins (i - 1, i + 1)for
Affecter un élément de tableaufor
Avancer de 2, aller à l'enversfor
Supprimer d'une List pendant la bouclefor, à l'envers
Une collection sans indexeur (HashSet, Dictionary, résultats LINQ)foreach
Répéter quelque chose N fois, sans collectionfor

Sur les tableaux, les deux boucles se compilent en un code quasiment identique, donc choisissez selon la lisibilité, pas la vitesse.

Questions fréquentes

Quelle est la syntaxe d'une boucle for en C# ?

for (initializer; condition; iterator) { body }, par exemple for (int i = 0; i < 5; i++) { ... }. L'initialiseur s'exécute une fois, la condition est vérifiée avant chaque itération, et l'itérateur s'exécute après chaque itération. La boucle s'arrête la première fois que la condition est fausse.

Comment parcourir une boucle à l'envers en C# ?

Commencez au dernier index et décrémentez : for (int i = items.Length - 1; i >= 0; i--). Notez >= 0 et non > 0, sinon le premier élément est ignoré. Parcourir à l'envers est aussi la façon sûre de supprimer des éléments d'une List pendant l'itération.

Quand utiliser for plutôt que foreach en C# ?

Utilisez for quand vous avez besoin de l'index (pour comparer des voisins, écrire dans un tableau ou avancer de plus d'un pas), quand vous comptez plutôt que de parcourir une collection, ou quand vous supprimez des éléments d'une liste. Utilisez foreach pour lire chaque élément dans l'ordre ; c'est plus court et il n'y a pas d'index à rater.

Comment écrire une boucle infinie en C# ?

for (;;) { ... } ou while (true) { ... }. Les trois parties de l'en-tête d'un for sont facultatives, et une condition absente compte comme vraie. Quittez la boucle avec break ou return quand votre condition de sortie est remplie.

Pourquoi ma boucle for lève-t-elle IndexOutOfRangeException ?

La condition laisse l'index atteindre la longueur : i <= array.Length visite array[array.Length], un cran après le dernier élément. Les index valides vont de 0 à Length - 1, donc la condition doit être i < array.Length (ou i < list.Count pour une List, qui lève ArgumentOutOfRangeException à la place).

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER