理想的C#IEnumerable通用数字序列,包含起始和间隔

时间:2013-05-13 17:23:03

标签: c# generics ienumerable ienumerator

我一直在寻找,但找不到实现IEnumerable的泛型类的惯用示例,它执行此操作:构造函数需要startinterval,而GetEnumerator返回{{ 1}},从开始开始,继续以间隔返回项目。

换句话说,比如:

IEnumerator

有很多相关的问题,小片段,点点滴滴,但是我还没有找到一个完整类的一个好例子,它至少做了类似的事情。这是关于如何实现这一点的,所以如果现有的类就是这样做的,那么知道这个问题会很好,但不能回答这个问题。

那么,实际的问题:哪个是最新的C#版本引入了对此有用的新功能,以及用它做这个的理想示例代码是什么?

此外,如果有任何常见的陷阱,那些缺乏经验的C#开发人员所犯的错误与这类课程有关,那就不错了。


更新:因为我要求的确切事情似乎是不可能的,我想下一个最好的事情是用lambda替换public class Sequence<T> : IEnumerable<T> where T :... { public T start { get; private set; } public T interval { get; private set; } Sequence(T start, T interval) { ... } IEnumerator<T> GetEnumerator() { for(T n = start ; ; n += interval) // does not compile yield return n; } ... what else? } 来获取下一个项目,或类似的东西。

3 个答案:

答案 0 :(得分:2)

感谢dlev​​建议Func,我最初只是使用帮助类。

public class Sequence<T> : IEnumerable<T>
{
  public T Start { get; private set; }
  public T Interval { get; private set; }
  private Func<T, T, T> Adder { get; set; }

  public Sequence(T start, T interval, Func<T,T,T> adder)
  {
    Start = start;
    Interval = interval;
    Adder = adder;
  }

  public IEnumerator<T> GetEnumerator()
  {
    for (T n = Start; ; n = Adder.Invoke(n, Interval))
      yield return n;
  }

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

然后您可以像这样使用它:

int i = 0;
foreach (int t in new Sequence<int>(3, 4, (int a, int b) => a + b))
{
    if (i == 10)
    {
        break;
    }
    i++;
    Console.WriteLine(t);
}

或者,您可以要求T实现某种Addable接口并调用Add方法,但我认为这种方法更加清晰。

答案 1 :(得分:2)

您所描述的内容与MoreLinqGenerate功能非常相似。

实施很简单:

public static IEnumerable<TResult> Generate<TResult>(TResult initial, Func<TResult, TResult> generator)
{
    if (generator == null) throw new ArgumentNullException("generator");
    return GenerateImpl(initial, generator);
}

private static IEnumerable<TResult> GenerateImpl<TResult>(TResult initial, Func<TResult, TResult> generator)
{
    TResult current = initial;
    while (true)
    {
        yield return current;
        current = generator(current);
    }
}

答案 2 :(得分:1)

作为使用委托的替代方法,您可以使用generic operators from MiscUtil。使用它,您的代码将如下所示:

IEnumerator<T> GetEnumerator() 
{
    for(T n = start ; ; n = Operator.Add(n, interval))
        yield return n; 
}