在第一次迭代后迭代 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; }
}
}
我的 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; }
}
}