为了账号安全,请及时绑定邮箱和手机立即绑定

IEnumerable和使用收益回报的递归

IEnumerable和使用收益回报的递归

C#
慕斯709654 2019-11-25 14:38:36
我有一种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同时使用递归的使用方法?
查看完整描述

3 回答

?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

在返回的方法内IEnumerable<T>,yield return必须返回T,而不是返回IEnumerable<T>。


更换


yield return c.GetDeepControlsByType<T>();

与:


foreach (var x in c.GetDeepControlsByType<T>())

{

  yield return x;

}


查看完整回答
反对 回复 2019-11-25
?
波斯汪

TA贡献1811条经验 获得超4个赞

您需要产生递归调用产生的每个项目:


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)

        {

            foreach (Control control in c.GetDeepControlsByType<T>())

            {

                yield return control;

            }

        }

    }

}

请注意,以这种方式进行递归会产生成本-您最终将创建大量的迭代器,如果您的控制树非常深,则可能会导致性能问题。如果要避免这种情况,则基本上需要在方法中自己进行递归,以确保仅创建一个迭代器(状态机)。有关更多详细信息和示例实现,请参见此问题 -但这显然也增加了一定数量的复杂性。


查看完整回答
反对 回复 2019-11-25
  • 3 回答
  • 0 关注
  • 392 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信