在C#中,如何最好地写出[0..100]?

15

我正在尝试想出巧妙、清晰和简单的方法来编写描述给定范围内整数序列的代码。

以下是一个示例:

IEnumerable<int> EnumerateIntegerRange(int from, int to)
{
    for (int i = from; i <= to; i++)
    {
        yield return i;
    }
}
4个回答

63

这已经在框架中了:Enumerable.Range

对于其他类型,您可能会对我的MiscUtil库中的区间类感兴趣。


3
@Sam:对我来说没问题,有什么不好的吗? - Kyle Cronin
2
@Sam:哪一个对你不起作用,你得到了什么? - Jon Skeet
IEnumerable<int> squares = Enumerable.Range(1, 10).Select(x => x * x); foreach (int num in squares) { Console.WriteLine(num); }相比之下(在Python中):for i in range(10): print i我喜欢编译语言为了实现简单的事情而费尽心思,就好像它越简单,编码就越难! - Andriy Drozdyuk
1
什么?在C#中,可以这样写:foreach(var i in Enumerable.Range(1, 10)) Console.WriteLine(i * i);...范围和打印函数的名称较长,并且Range需要一个起始参数。除了i之外,没有其他变量,也没有lambda表达式。 - Jeffrey Hantin

7

或者,使用扩展方法的流畅接口:

public static IEnumerable<int> To(this int start, int end)
{
    return start.To(end, i => i + 1);
}

public static IEnumerable<int> To(this int start, int end, Func<int, int> next)
{
    int current = start;
    while (current < end)
    {
        yield return current;
        current = next(current);
    }
}

用法如下:

1.To(100)

个人而言,我更喜欢扩展方法的阅读方式。尽管如此,我对扩展方法有点偏爱(我为VB实现了它们)。我从来没有理解为什么C#的开发者一开始没有将Range作为扩展方法。 - Scott Wisniewski

0
这是一个让范围类可以处理离散和连续事物的想法:
class Range<T> where T: IComparable<T>
{
    public T From { get; set; }
    public T To { get; set; }

    public Range(T from, T to) { this.From = from; this.To = to; }

    public IEnumerable<T> Enumerate(Func<T, T> next)
    {
        for (T t = this.From; t.CompareTo(this.To) < 0; t = next(t))
        {
            yield return t;
        }
    }

    static void Example()
    {
        new Range<int> (0, 100).Enumerate(i => i+1)
    }
}

0

如果你认为每次提供枚举器都很烦人,这里有一个派生类:

class EnumerableRange<T> : Range<T>, IEnumerable<T>
    where T : IComparable<T>
{
    readonly Func<T, T> _next;
    public EnumerableRange(T from, T to, Func<T, T> next)
        : base(from, to)
    {
        this._next = next;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return Enumerate(this._next).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

1
我发现使用Range类和独立的RangeIterator类提供更好的分离。除此之外,这意味着您的Range可以是不可变的和封闭的,这很好。MiscUtil中的版本有各种方法(扩展和其他方法)在两者之间进行转换。 - Jon Skeet
是的,我看到MiscUtil中的那个。我的范围可以是不可变的;对我来说唯一需要可变性的原因是它允许C#对象初始化程序。我可能应该选择不可变性。 - Jay Bazuzi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接