77 votes

Existe-t-il une version plus courte/simple de la boucle for pour faire quelque chose x fois ?

Habituellement, nous faisons quelque chose comme une boucle for ou while avec un compteur :

for (int i = 0; i < 10; i++)
{
    list.Add(GetRandomItem());
}

mais parfois tu te mélanges avec les limites. Vous pourriez utiliser une boucle while à la place, mais si vous faites une erreur, cette boucle est infinie...

En Perl, par exemple, j'utiliserais la méthode plus évidente suivante

for(1..10){
    list->add(getRandomItem());
}

Y a-t-il quelque chose comme doitXtimes(10){...} ?

93voto

Jon Skeet Points 692016

Vous pouvez facilement écrire votre propre méthode d'extension :

public static void Times(this int count, Action action)
{
    for (int i = 0; i < count; i++)
    {
        action();
    }
}

Ensuite, vous pourrez écrire :

10.Times(() => list.Add(GetRandomItem()));

Je ne suis pas sûr que je suggérerais en fait que vous do mais c'est une option. Je ne crois pas qu'il y ait quelque chose comme ça dans le cadre, bien que vous puissiez utiliser Enumerable.Range ou Enumerable.Repeat pour créer une séquence paresseuse d'une longueur appropriée, ce qui peut être utile dans certaines situations.


Depuis C# 6, il est toujours possible d'accéder à une méthode statique sans créer de méthode d'extension, en utilisant une méthode de type using static pour l'importer. Par exemple :

// Normally in a namespace, of course.
public class LoopUtilities
{
    public static void Repeat(int count, Action action)
    {
        for (int i = 0; i < count; i++)
        {
            action();
        }
    }
}

Puis, quand vous voulez l'utiliser :

using static LoopUtilities;

// Class declaration etc, then:
Repeat(5, () => Console.WriteLine("Hello."));

71voto

Grozz Points 3586
foreach (var i in Enumerable.Range(0, N))
{
    // do something
}

2 votes

Cette version est agréable, lorsque vous avez besoin de l'index.

1 votes

Succinct et efficace - l'index peut toujours être ignoré s'il n'est pas nécessaire.

2 votes

C'est celui que j'ai choisi, car il fournit une manière succincte mais claire de faire l'itération. J'ai l'impression qu'elle est beaucoup plus compacte que la réponse de Paul, bien qu'il s'agisse en fait de la même solution.

40voto

Paul Ruane Points 12840

On peut créer un IEnumerable de Int32 :

Enumerable.Range(0, 10);

En ForEach La méthode d'extension est également largement connue (bien qu'elle ne soit pas livrée avec .NET). Vous pourriez combiner les deux :

Enumerable.Range(0, 10).ForEach(index => ...);

Votre exemple deviendrait donc :

Enumerable.Range(0, 10).ForEach(_ => list.Add(GetRandomItem()));

0 votes

@mbx : Oui, la méthode Times de Jon Skeet est bien meilleure lorsque l'indice n'est pas nécessaire et que vous voulez juste répéter une opération.

3 votes

BTW Je n'ai pas de ForEach sans la fonction ToList Enumerable.Range(0, 10).ToList().ForEach(i => sb.AppendLine($"{i}")) ; Ils devraient faire un lambda dédié pour cela.

16voto

Alex Baranosky Points 10595

Je vois Jon Skeet m'a devancé mais cette variante vous permettra de transmettre l'index à l'action chaque fois qu'elle est exécutée :

public static class IntegerExtensions
{
  public static void TimesWithIndex(this int count, Action<int> action)
  {
     for (int i = 0; i < count; i++)
        action(i);
  }
}

Et appelez ça comme ça :

10.TimesWithIndex((i) =>
            obj[i].DoSomething());

8voto

aaimnr Points 1095
while (i-- > 0) {

}

Vous avez mentionné que la boucle while est dangereuse car elle peut être infinie - la forme ci-dessus est assez simple et ne sera jamais infinie. Au moins TOTALEMENT infinie :)

Elle est pratique et courte (plus courte que toutes les autres réponses) et fonctionnera exactement comme suit i fois (parce que la décrémentation postfixe retourne la valeur avant la décrémentation).

5 votes

Vous avez manqué la déclaration et l'initialisation des variables, ce qui rendrait votre version inférieure à la version demandée. for(1..10) et la réponse sélectionnée de int.Times via la méthode d'extension.

0 votes

En effet, le meilleur cas d'utilisation de ce scénario est celui où vous déclarez/initialisez le nombre de boucles dans des instructions précédentes en utilisant une logique plus complexe et où vous appliquez simplement la logique de boucle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X