我一直在寻找,但找不到实现IEnumerable的泛型类的惯用示例,它执行此操作:构造函数需要start
和interval
,而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?
}
来获取下一个项目,或类似的东西。
答案 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)
您所描述的内容与MoreLinq的Generate
功能非常相似。
实施很简单:
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;
}