理想的c# IEnumerable通用数字序列的开始和间隔
本文关键字:开始 字序 数字 IEnumerable 理想 | 更新日期: 2023-09-27 18:13:24
我一直在寻找,但找不到一个实现IEnumerable的通用类的惯用示例,它这样做:构造函数接受start
和interval
, GetEnumerator
返回IEnumerator
,它从start开始,一直返回具有间隔的项目。
换句话说,就像:
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?
}
有很多相关的问题和小片段,但我还没有找到一个完整类的好例子,它至少做了一些类似的事情。这是关于如何实现这个,所以如果有一个现有的类做这个,这将是很好的知道,但不是一个问题的答案。
所以,实际的问题是:哪一个最新的c#版本引入了有用的新功能,用它来完成这个任务的理想示例代码是什么?如果没有经验的c#开发人员在使用这种类时会犯一些常见的陷阱和错误,那么最好知道这些。
更新:因为我要求的确切的事情似乎是不可能的,我想下一个最好的事情是用lambda代替interval
来获得下一个项目,或类似的东西。
感谢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
方法,但我认为这更清晰。
您所描述的与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);
}
}
作为使用委托的替代方法,您可以使用MiscUtil中的泛型操作符。使用它,您的代码看起来像这样:
IEnumerator<T> GetEnumerator()
{
for(T n = start ; ; n = Operator.Add(n, interval))
yield return n;
}