我在制作可以遍历以下类型的数据结构的迭代器时遇到了一些麻烦。
我有一个名为Expression
的班级,其中有一个数据成员a List<object>
。
此列表可以包含任意数量的子项,其中一些子项可能是其他Expression对象。
我想遍历这个结构,并打印出每个非列表对象(但我确实要打印出列表中的元素),但在输入列表之前,我想返回“begin nest”和在我刚刚退出列表后,我想返回“结束巢”。
如果我在可能的情况下忽略了这个类,我就能做到这一点,如果我想要一个subExpression,只有List<object>
个List<object>
个对象,但我宁愿废除它,而是有一个Expression
作为子列表(这样可以更容易对对象进行操作。我知道我可以在List<object>
上使用扩展方法但是它不适合(谁想要一个列表中不带参数的Evaluate
方法?)。
我用来生成原始迭代器(有效)的代码是:
public IEnumerator GetEnumerator(){
return theIterator(expr).GetEnumerator();
}
private IEnumerable theIterator(object root) {
if ((root is List<object>)){
yield return " begin nest ";
foreach (var item in (List<object>)root){
foreach (var item2 in theIterator(item)){
yield return item2;
}
}
yield return " end nest ";
}
else
yield return root;
}
表达式List<object>
的类型交换不起作用,并导致stackOverflow错误。如何实现迭代器?
更新:以下是交换代码:
public IEnumerator GetEnumerator() {
return this.GetEnumerator();
}
private IEnumerable theIterator(object root) {
if ((root is Expression)) {
yield return " begin nest ";
foreach (var item in (Expression)root) {
foreach (var item2 in theIterator(item))
yield return item2;
}
yield return " end nest ";
}
else
yield return root;
}
答案 0 :(得分:2)
您获得StackOverflowException
的原因是
foreach (var item in (Expression)root)
......内部导致:
((Expression)root).GetEnumerator()
...要调用 - 这是CLR枚举在item
循环的每次迭代期间必须分配给foreach
变量的对象的方式。
在您的情况下,GetEnumerator()
调用会导致theIterator
再次针对同一root
执行,从而进入无限递归。
要解决您的问题,您需要替换:
foreach (var item in (Expression)root)
...与:
foreach (var item in ((Expression)root).expr)
...其中expr
是List<object>
属性的名称。
答案 1 :(得分:2)
为什么要将GetEnumerator()
更改为this.GetEnumerator()
?
在我看来,你的堆栈溢出来自哪里。
尝试让它返回theIterator(this).GetEnumerator()
?