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

时间:2015-05-19 08:32:08

标签: c# ienumerable ienumerator

我的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]

班级Reeks看起来像这样

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而不是之后应该出现的值。

2 个答案:

答案 0 :(得分: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;

哪个会返回false。

修改

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

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

答案 1 :(得分:1)

不确定为什么你需要http .authorizeRequests() .antMatchers("/non-secure/**").permitAll() .antMatchers("/secure/**").hasAuthority("user") .and().requiresChannel().antMatchers("/non-secure/**").requiresInsecure() .and().requiresChannel().antMatchers("/secure/**").requiresSecure() List<T>中的if (idx < reeks.Count - 1)在第二次迭代中失败。

如果没有必要实现自定义迭代器,我会用迭代器块来做。

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>