在第一次迭代后迭代 IEnumerable 停止点

Iterate over IEnumerable stops after first iteration

我的 Main() 方法中有以下内容

Reeks r = new Reeks();

foreach(int i in r){
    if(i < 1000){
        Console.WriteLine(i);
    }
}

我想要的是遍历 Reeks 直到 i > 1000 的值,其中 i 是前一个值乘以 2,即 [1,2,4,8,16,32].

classReeks看起来像这样

class Reeks : IEnumerable<int>, IEnumerator<int>
{
    private List<int> reeks;
    private int idx = -1;

    public Reeks()
    {
        reeks = new List<int>() {1};
    }

    public IEnumerator<int> GetEnumerator()
    {
        return this;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this;
    }

    public void Dispose()
    {

    }

    public bool MoveNext()
    {
        if (idx < reeks.Count - 1)
        {
            idx++;
            return true;
        }
        return false;
    }

    public void Reset()
    {
        idx = -1;
    }

    public int Current
    {
        get
        {
            if (idx == -1)
            {
                throw new InvalidOperationException("Enumeration has not started. Call MoveNext");
            }
            else
            {
                if (idx != 0)
                {
                    reeks.Add((reeks[(idx-1)]*2));
                }
                return reeks[idx];
            }
        }
    }

    object IEnumerator.Current
    {
        get { return Current; }
    }
}

问题是它在第一次迭代后停止迭代,它只打印开头的 1 而不是之后应该出现的值。

嗯,这很简单。您的 List 只有一个元素。当遍历 Reeks(因此调用 MoveNext())时,您将 idx 增加 1。仍然可以。

但是,您的 MoveNext() 定义为

public bool MoveNext()
{
    if (idx < reeks.Count - 1)
    {
        idx++;
        return true;
    }
    return false;
}

让我们迭代前两个;

迭代 1

idx = -1;
reeks.Count = 1; //Because reeks is a List containing 1 element

if(-1 < 0)
{
    idx++;
    return true;
}

哪个有效。

迭代 2

idx = 0; //incremented -1 by 1
reeks.Count = 1; //Not altered

if(0 < 0)
{
    //Not reached!
}

return false;

哪个会 return 错误。

编辑

Sriram 提供的答案可能是最好和最优雅的。但是,如果您必须坚持使用当前的代码,您确实可以在 MoveNext() 方法中添加下一个元素。这也将使它无限。

public bool MoveNext()
{
    int size = reeks.Count - 1;
    if (idx < size)
    {
        idx++;
        reeks.Add(reeks[size]*2);
        return true;
    }
    return false;
}

不确定为什么需要 List<T>if (idx < reeks.Count - 1) in MoveNext 在第二次迭代中失败。

如果不需要实现自定义迭代器,我会使用迭代器块来实现。

private static IEnumerable<int> Reeks()
{
    int num = 1;
    yield return num;

    while (true)
    {
        num = num * 2;
        yield return num;
    }
}

然后用作

foreach (int i in Reeks().TakeWhile(x => x < 1000))
{
    Console.WriteLine(i);
}

正如您在评论中所说,这必须是自定义迭代器。手写的迭代器块看起来像这样。请注意 List<T> 已删除,您不需要列表。你只需要知道最后返回的值是多少。

class Reeks : IEnumerable<int>, IEnumerator<int>
{
    private int current;
    private int idx = -1;

    public IEnumerator<int> GetEnumerator()
    {
        return this;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this;
    }

    public void Dispose()
    {
        Reset();
    }

    public bool MoveNext()
    {
        if (idx == -1)
        {
            idx = 0;
            current = 1;
        }
        else
        {
            current = current * 2;
        }

        return true;
    }

    public void Reset()
    {
        idx = -1;
    }

    public int Current
    {
        get
        {
            if (idx == -1)
                throw new InvalidOperationException("Enumeration has not started. Call MoveNext");

            return current;
        }
    }

    object IEnumerator.Current
    {
        get { return Current; }
    }
}