C# IEnumerable在无限序列上跳过
我有一个使用BigInteger的Fibonacci序列的简单实现:C# IEnumerable在无限序列上跳过,c#,linq,fibonacci,skip,C#,Linq,Fibonacci,Skip,我有一个使用BigInteger的Fibonacci序列的简单实现: internal class FibonacciEnumerator : IEnumerator<BigInteger> { private BigInteger _previous = 1; private BigInteger _current = 0; public void Dispose(){} public bool MoveN
internal class FibonacciEnumerator : IEnumerator<BigInteger>
{
private BigInteger _previous = 1;
private BigInteger _current = 0;
public void Dispose(){}
public bool MoveNext() {return true;}
public void Reset()
{
_previous = 1;
_current = 0;
}
public BigInteger Current
{
get
{
var temp = _current;
_current += _previous;
_previous = temp;
return _current;
}
}
object IEnumerator.Current { get { return Current; }
}
}
internal class FibonacciSequence : IEnumerable<BigInteger>
{
private readonly FibonacciEnumerator _f = new FibonacciEnumerator();
public IEnumerator<BigInteger> GetEnumerator(){return _f;}
IEnumerator IEnumerable.GetEnumerator(){return GetEnumerator();}
}
输出如预期的1,1,2,3,5,8
我想选择10项,但从第100位开始。我试着打电话给他
fs.Skip(100).Take(10).ToList().ForEach(_ => Console.WriteLine(_));
但这不起作用,因为它从一开始就输出十个元素,即输出再次为1,1,2,3,5,8
我可以打电话跳过它
fs.SkipWhile((b,index) => index < 100).Take(10).ToList().ForEach(_ => Console.WriteLine(_));
从第100个元素开始正确输出10个元素
在枚举器中是否还有其他需要/可以实现的内容,以使跳过。。。工作?Skipn不访问当前,它只调用MoveNext n次
因此需要在MoveNext中执行增量,即:
Current不会移动枚举数的位置,对Current的连续调用将返回相同的对象,直到调用MoveNext或Reset
将逻辑移到MoveNext:
Skip10只是调用MoveNext 10次,然后调用Current。在MoveNext中执行操作比在current中执行操作更有逻辑意义。CodeCaster的答案很准确-我只想指出,对于这样的事情,您实际上不需要实现自己的枚举:
public IEnumerable<BigInteger> FibonacciSequence()
{
var previous = BigInteger.One;
var current = BigInteger.Zero;
while (true)
{
yield return current;
var temp = current;
current += previous;
previous = temp;
}
}
编译器将为您创建枚举数和可枚举数。对于这样一个简单的可枚举函数,差别并不是很大,你只需要避免大量的样板文件,但是如果你真的需要比简单递归函数更复杂的东西,它会产生巨大的差别。。收益率返回是您的朋友。如果您使用的是正确的c版本,则不确定您可以使用哪个atm收益率和收益率返回,这为我节省了很多精力,并且消除了定义新的枚举器类bc的麻烦。在您的情况下,多次访问Current会产生不同的结果。不应该。嗯,有副作用的吸气剂!肮脏的
public bool MoveNext()
{
var temp = _current;
_current += _previous;
_previous = temp;
return true;
}
public void Reset()
{
_previous = 1;
_current = 0;
}
public BigInteger Current
{
get
{
return _current;
}
}
public IEnumerable<BigInteger> FibonacciSequence()
{
var previous = BigInteger.One;
var current = BigInteger.Zero;
while (true)
{
yield return current;
var temp = current;
current += previous;
previous = temp;
}
}