IEnumerable和使用收益回报的递归

我有一种IEnumerable<T>用于在WebForms页面中查找控件的方法。


该方法是递归的,当返回yield return值为递归调用的值时,在返回所需的类型时遇到一些问题。


我的代码如下所示:


    public static IEnumerable<Control> 

                               GetDeepControlsByType<T>(this Control control)

    {

        foreach(Control c in control.Controls)

        {

            if (c is T)

            {

                yield return c;

            }


            if(c.Controls.Count > 0)

            {

                yield return c.GetDeepControlsByType<T>();

            }

        }

    }

当前,这将引发“无法转换表达式类型”错误。但是IEnumerable<Object>,如果此方法返回type ,则代码会生成,但是在输出中返回了错误的类型。


有没有yield return同时使用递归的使用方法?


慕斯709654
浏览 425回答 3
3回答

慕无忌1623718

在返回的方法内IEnumerable<T>,yield return必须返回T,而不是返回IEnumerable<T>。更换yield return c.GetDeepControlsByType<T>();与:foreach (var x in c.GetDeepControlsByType<T>()){&nbsp; yield return x;}

波斯汪

您需要产生递归调用产生的每个项目:public static IEnumerable<Control> GetDeepControlsByType<T>(this Control control){&nbsp; &nbsp; foreach(Control c in control.Controls)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (c is T)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return c;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if(c.Controls.Count > 0)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (Control control in c.GetDeepControlsByType<T>())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return control;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}请注意,以这种方式进行递归会产生成本-您最终将创建大量的迭代器,如果您的控制树非常深,则可能会导致性能问题。如果要避免这种情况,则基本上需要在方法中自己进行递归,以确保仅创建一个迭代器(状态机)。有关更多详细信息和示例实现,请参见此问题 -但这显然也增加了一定数量的复杂性。
打开App,查看更多内容
随时随地看视频慕课网APP