递归迭代器

时间:2012-06-03 22:12:00

标签: c# recursion iterator

我在制作可以遍历以下类型的数据结构的迭代器时遇到了一些麻烦。

我有一个名为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;
    }

2 个答案:

答案 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)

...其中exprList<object>属性的名称。

答案 1 :(得分:2)

为什么要将GetEnumerator()更改为this.GetEnumerator()

在我看来,你的堆栈溢出来自哪里。

尝试让它返回theIterator(this).GetEnumerator()