81 votes

Réflexions sur le foreach avec Enumerable.Range vs traditionnel pour la boucle

En C# 3.0, j'aime ce style :

// Write the numbers 1 thru 7
foreach (int index in Enumerable.Range( 1, 7 ))
{
    Console.WriteLine(index);
}

sur la boucle traditionnelle for :

// Write the numbers 1 thru 7
for (int index = 1; index <= 7; index++)
{
    Console.WriteLine( index );
}

En supposant que « n » soit petit, donc la performance n'est pas un problème, quelqu'un s'oppose-t-il au nouveau style plutôt qu'au style traditionnel ?

47voto

LukeH Points 110965

C'est juste pour s'amuser. (Je n'utiliserais que le format de boucle standard "for (int i = 1; i <= 10; i++)" moi-même.)

foreach (int i in 1.To(10))
{
    Console.WriteLine(i);    // 1,2,3,4,5,6,7,8,9,10
}

// ...

public static IEnumerable<int> To(this int from, int to)
{
    if (from < to)
    {
        while (from <= to)
        {
            yield return from++;
        }
    }
    else
    {
        while (from >= to)
        {
            yield return from--;
        }
    }
}

Vous pouvez également ajouter une méthode d'extension Step :

foreach (int i in 5.To(-9).Step(2))
{
    Console.WriteLine(i);    // 5,3,1,-1,-3,-5,-7,-9
}

// ...

public static IEnumerable<T> Step<T>(this IEnumerable<T> source, int step)
{
    if (step == 0)
    {
        throw new ArgumentOutOfRangeException("step", "Param cannot be zero.");
    }

    return source.Where((x, i) => (i % step) == 0);
}

27voto

tsayper Points 1

En C# 6.0 avec l'utilisation de

using static System.Linq.Enumerable;

vous pouvez le simplifier pour

foreach (var index in Range(1, 7))
{
    Console.WriteLine(index);
}

12voto

THX-1138 Points 7129

Vous pouvez réellement le faire en C# (en fournissant To et Do comme méthodes d'extension sur int et IEnumerable<T> respectivement) :

1.To(7).Do(Console.WriteLine);

SmallTalk pour toujours !

9voto

Kache Points 2182

J'aime bien l'idée. C'est un peu comme Python. Voici ma version en quelques lignes :

static class Extensions
{
    public static IEnumerable<int> To(this int from, int to, int step = 1) {
        if (step == 0)
            throw new ArgumentOutOfRangeException("step", "step cannot be zero");
        // stop if next `step` reaches or oversteps `to`, in either +/- direction
        while (!(step > 0 ^ from < to) && from != to) {
            yield return from;
            from += step;
        }
    }
}

Il fonctionne comme celui de Python :

  • 0.To(4)[ 0, 1, 2, 3 ]
  • 4.To(0)[ 4, 3, 2, 1 ]
  • 4.To(4)[ ]
  • 7.To(-3, -3)[ 7, 4, 1, -2 ]

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