Instructions d’itération

Tip

Cet article fait partie de la section Notions de base pour les développeurs qui connaissent déjà au moins un langage de programmation et apprennent C#. Si vous débutez avec la programmation, commencez par commencer par les didacticiels De prise en main . Pour obtenir la syntaxe complète, consultez les instructions d’itération dans la référence du langage.

Venant d’une autre langue ? Les quatre boucles C# (foreach, while, do-whileet for) ont des équivalents directs dans Java, C++et JavaScript. Vous utilisez foreach le plus souvent. Il permet d’itérer sur une collection sans indice, comme avec le for amélioré de Java ou le for...of de JavaScript.

Les instructions d’itération exécutent un bloc de code à plusieurs reprises. Chaque passage du bloc est une itération et un bloc répétitif est une boucle. C# fournit quatre boucles. Commencez par foreach les regroupements, utilisez while etdo-whilequand une condition contrôle la répétition, puis utilisez for quand vous avez besoin d’un index explicite.

Itérer une collection avec foreach

L’instruction foreach exécute son corps une fois pour chaque élément d’une collection, dans l’ordre. Il s’agit du choix le plus courant pour lire une collection, car vous ne gérez pas d’index ou de vérification des limites. L’instruction foreach empêche les erreurs off-by-one classiques :

string[] names = ["Ana", "Ben", "Cleo"];

// foreach reads each element in order. It's the default loop for
// collections: no index to manage and no off-by-one mistakes.
foreach (string name in names)
{
    Console.WriteLine(name); // => Ana, then Ben, then Cleo
}

foreach fonctionne avec n’importe quel type que C# reconnaît en tant que séquence, y compris les tableaux, List<T>et Dictionary<TKey,TValue>. La variable d’itération (name dans l’exemple précédent) est en lecture seule. Vous ne pouvez donc pas la réaffecter à l’intérieur de la boucle.

Le corps d’une boucle est une instruction unique, telle qu’une affectation ou un appel de méthode. Un bloc d’instructions est en lui-même une instruction unique qui englobe zéro, une ou plusieurs instructions entre accolades ({ }).

De nombreuses normes de codage recommandent d’entourer le corps de la boucle d’accolades, même pour une seule instruction. Les accolades rendent la portée explicite. Cela évite une erreur courante : le fait d’ajouter plus tard une deuxième ligne que vous pensez exécuter à chaque itération, alors qu’en réalité elle ne s’exécute qu’une seule fois après la boucle. Seuls les accolades déterminent quelles instructions appartiennent à la boucle. C# ne traite pas les espaces blancs comme significatifs, de sorte que la mise en retrait seule ne le fait jamais. Les accolades sont autorisées même autour d’une seule ligne : le bloc correspond à l’unique instruction répétée par la boucle. Indentez votre code pour en améliorer la lisibilité, mais fiez-vous aux accolades pour définir le bloc.

Répéter tant qu’une condition est vraie while

Une while boucle vérifie sa condition booléenne avant chaque itération. Si la condition est false au début, le corps ne s’exécute jamais, donc une while boucle s’exécute zéro ou plusieurs fois :

int countdown = 3;

// A while loop checks its condition before each iteration, so the body
// runs zero or more times.
while (countdown > 0)
{
    Console.WriteLine(countdown); // => 3, then 2, then 1
    countdown--;
}

Assurez-vous que quelque chose à l’intérieur de la boucle modifie la condition. Dans l’exemple précédent, countdown-- fait finalement la condition false. Une boucle dont la condition ne devient jamais false s’exécute indéfiniment.

Exécutez le bloc au moins une fois avec do-while

Une do-while boucle vérifie sa condition après chaque itération, de sorte que le corps s’exécute toujours au moins une fois. Utilisez-la lorsque la première passe doit se produire avant de pouvoir évaluer la condition, telle que l’invite d’entrée, puis la validation :

int attempts = 0;

// A do-while loop runs its body once, then checks the condition. Use it
// when the body must run at least one time.
do
{
    attempts++;
    Console.WriteLine($"Attempt {attempts}"); // => Attempt 1, then Attempt 2, then Attempt 3
}
while (attempts < 3);

Compter à l’aide de for

Une for instruction de boucle contient trois parties : un initialiseur qui s’exécute une fois avant la boucle, une condition vérifiée avant chaque itération et un itérateur qui s’exécute après chaque itération. Utilisez for quand vous avez besoin de l’index lui-même, pas seulement des éléments. En règle générale, vous avez besoin de l’index lorsque vous souhaitez modifier l’élément plutôt que de lire sa valeur.

// A for loop fits when you need an explicit index. The three parts are
// the initializer, the condition, and the iterator.
for (int i = 0; i < 3; i++)
{
    Console.WriteLine(i); // => 0, then 1, then 2
}

Lorsque vous lisez uniquement les éléments, lorsque vous n’utilisez pas les positions ou que vous affectez de nouvelles valeurs, préférez foreach. Il indique plus clairement l’intention et évite l’arithmétique de l’index.

Quitter ou ignorer avec break et continue

Deux instructions de saut vous offrent un contrôle plus fin au sein de toute boucle. L’instruction break quitte immédiatement la boucle, en ignorant les itérations restantes :

int[] numbers = [2, 4, 7, 8];

// break stops the loop immediately, skipping any remaining elements.
foreach (int number in numbers)
{
    if (number % 2 != 0)
    {
        Console.WriteLine($"First odd number: {number}"); // => First odd number: 7
        break;
    }
}

L’instruction continue ignore le reste de l’itération actuelle et passe à la suivante :

int[] values = [1, 2, 3, 4, 5];

// continue skips the rest of the current iteration and moves to the next.
foreach (int value in values)
{
    if (value % 2 == 0)
    {
        continue; // skip even numbers
    }

    Console.WriteLine(value); // => 1, then 3, then 5
}

Itérer un flux asynchrone avec await foreach

Un flux asynchrone est un lecteur qui utilise une tâche asynchrone pour produire chaque élément suivant. C# le représente avec l’interface IAsyncEnumerable<T> . Les données qui arrivent au fil du temps, telles que les pages d’une API web ou de lignes d’une base de données, correspondent à ce modèle : la récupération de l’élément suivant est une opération attendable au lieu d’un retour immédiat.

Pour consommer un flux asynchrone, placez le await mot clé avant foreach. Chaque itération attend l’élément suivant, de sorte que la boucle s’interrompt pendant que cet élément est produit au lieu de bloquer le thread :

private static async Task AwaitForeachExample()
{
    // await foreach consumes an asynchronous stream. Each iteration can
    // suspend while the next element is produced.
    await foreach (int value in GenerateAsync())
    {
        Console.WriteLine(value); // => 0, then 1, then 2
    }
}

private static async IAsyncEnumerable<int> GenerateAsync()
{
    for (int i = 0; i < 3; i++)
    {
        await Task.Delay(1); // stand-in for real asynchronous work
        yield return i;
    }
}

Les flux asynchrones s’appuient sur async et await. Pour obtenir une procédure pas à pas complète, consultez Générer et consommer des flux asynchrones.

Voir aussi