收益率递归

时间:2013-09-23 07:27:30

标签: c# recursion yield

我正在尝试创建一个

    IEnumrable<PropertyInfo> 

我有一个名为Disassemble的方法,它以递归的方式迭代抛出一个给定的对象及其所有属性的子对象。

请不要关注自己使用INameValueWrapper类型的内包装器对象

下面的问题是当我遇到一个属于I类的属性时,我也不想在它上面调用Disassemble 并将其添加到IEnumrable的同一迭代中,Dissasemble在调用时不会再次出现 在哪里我发表评论:      //问题在这里。

    public static IEnumerable<T> Dissasemble<T>(this object sourceObj) where T : INameValueWrapper
    {
        var properties = sourceObj.GetType().GetProperties();

        foreach (var prop in properties)
        {
            var wrapper = (T)prop.WrapPropertyInfo(sourceObj);
            yield return wrapper;

            if (wrapper is CollectionPropertyInfoWrapper)
            {
                var colWrapper = wrapper as CollectionPropertyInfoWrapper;
                var collection = (IList)colWrapper.Value;

                int index = 0;
                foreach (var item in collection)
                {
                    yield return (T)item.WrapItem(collection, index + 1);
                    index++;
                }
            }
            else
            {
                var propWrapper = wrapper as PropertyInfoWrapper;
                if (!propWrapper.IsPrimitive)
                {
                    var childObject = prop.GetValue(sourceObj);
                    childObject.Dissasemble<T>(); // here is the problem 
                }
            }
        }

        yield break;
    } 

1)为什么不调用它并将其添加到迭代中?

2)围绕这个问题的工作是什么? ,

 i could call childObject.Dissasemble<T>().ToList() 
 and then iterate that collection calling yield return on it's items 
 but that seems like re doing something i already did.

提前感谢。

2 个答案:

答案 0 :(得分:5)

您正在调用该方法,但忽略了结果。你可能想要这样的东西:

foreach (var item in childObject.Disassemble<T>())
{
    yield return item;
}

我认为你对yield return的作用感到有点困惑 - 它只会在当前执行的方法返回的序列中产生一个值。它不会为某些全局序列添加值。如果忽略递归Disassemble调用返回的值,则代码甚至不会执行,因为迭代器块是惰性的。 (它们只在被要求提供其他值时执行代码。)

此外,您不需要在方法结束时使用yield break;

请注意,如果递归变深,则使用迭代器块可能效率低下。这对你来说可能不是一个问题,但这是值得思考的问题。请参阅Wes DyerEric Lippert关于此的帖子。

答案 1 :(得分:3)

而不是

childObject.Dissasemble<T>(); // here is the problem 

foreach (var a in childObject.Dissasemble<T>())
{
 yield return a;
}