Is there a C# equivalent of Python's range with step?
Documentation:
For a positive
step, the contents of a rangerare determined by the formular[i] = start + step*iwherei >= 0andr[i] < stop.For a negative
step, the contents of the range are still determined by the formular[i] = start + step*i, but the constraints arei >= 0andr[i] > stop.
Example:
>>> list(range(0, 10, 3))
[0, 3, 6, 9]
>>> list(range(0, -10, -1))
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
                I would go with two methods implementation. First one for parameters validation and providing defaults:
public static IEnumerable<int> Range(int start, int stop, int step = 1)
{
    if (step == 0)
        throw new ArgumentException(nameof(step));
    return RangeIterator(start, stop, step);
}
That is required for iterators with deferred execution. Otherwise, you will not validate arguments until iterator will be executed. Which might happen a long time after you get an iterator reference. And iterator itself (actually with C# 7 you can use a local function instead of creating separate method):
private static IEnumerable<int> RangeIterator(int start, int stop, int step)
{
    int x = start;
    do
    {
        yield return x;
        x += step;
        if (step < 0 && x <= stop || 0 < step && stop <= x)
            break;
    }
    while (true);
}
To implement Python's range behavior we need one more method which accepts only stop parameter. We can simplify code with C# 6 expression-bodied member:
public static IEnumerable<int> Range(int stop) => RangeIterator(0, stop, 1);
You also can make static methods available in global scope with C# 6. Assume class with Range method description is named PythonUtils:
using static YourNamespace.PythonUtils;
And usage in code will look like
foreach(var i in Range(0, 10, 3))
   Print(i);
You can also use default values
Range(0, 10, 3)     // [0,3,6,9]
Range(4, -3, -1)    // [4,3,2,1,0,-1,-2]
Range(5)            // [0,1,2,3,4]
Range(2, 5)         // [2,3,4]
Looks like Pascal-case Python :)
We can implement a static utility class to handle this.
For completeness, this solution mimics Python's range behavior for one parameter (stop), two parameters (start, stop), and three parameters (start, stop, step):
using System;
using System.Collections.Generic;
public static class EnumerableUtilities
{
    public static IEnumerable<int> RangePython(int start, int stop, int step = 1)
    {
        if (step == 0)
            throw new ArgumentException("Parameter step cannot equal zero.");
        if (start < stop && step > 0)
        {
            for (var i = start; i < stop; i += step)
            {
                yield return i;
            }
        }
        else if (start > stop && step < 0)
        {
            for (var i = start; i > stop; i += step)
            {
                yield return i;
            }
        }
    }
    public static IEnumerable<int> RangePython(int stop)
    {
        return RangePython(0, stop);
    }
}
Example Usage with Step:
foreach (var i in EnumerableUtilities.RangePython(0, 10, 3))
{
    Console.WriteLine(i);
}
Output:
0
3
6
9
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With