yield return in recursion

故事扮演 提交于 2019-12-11 01:39:09

问题


i am attempting to create an

    IEnumrable<PropertyInfo> 

iv'e got a method called Disassemble which iterates recursively throw a given object and all it's child objects of it's properties .

please do not concern your self with the Inner wrapper objects of type INameValueWrapper

The problem below is when i encounter a property which is a Class i wan't to call Disassemble on it as well and add it to the same iteration of the IEnumrable , the Dissasemble does not occur again when it is called where i put the comment : // The problem is here .

    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) Why does it not get called and added to the iteration ?

2) What is the work around this issue ? ,

 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.

thanks in advance.


回答1:


You're calling the method, but then ignoring the results. You may want something like:

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

I think you're a bit confused about what yield return does - it only yields a value in the sequence returned by the currently-executing method. It doesn't add a value to some global sequence. If you ignore the value returned by the recursive Disassemble call, the code won't even execute as iterator blocks are lazy. (They only execute code when they're asked for another value.)

Also, you don't need the yield break; at the end of your method.

Note that this if the recursion goes deep, this use of iterator blocks can be inefficient. That may well not be a problem for you, but it's something to think about. See posts by Wes Dyer and Eric Lippert about this.




回答2:


Instead of

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

try

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


来源:https://stackoverflow.com/questions/18953817/yield-return-in-recursion

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!