遍历对象图并返回访问节点的递归yield方法

本文关键字:递归 yield 方法 节点 访问 对象图 返回 遍历 | 更新日期: 2023-09-27 18:21:18

我正在尝试编写一个扩展方法,该方法应该遍历对象图并返回所有访问的对象。

我不确定我的方法是否是最好的,所以请对此发表评论。产量也在炒我的大脑。。。我相信答案是显而易见的:/

型号

public class MyClass
{
    public MyClass Parent {get;set;}
}

方法

public static IEnumerable<T> SelectNested<T>
    (this T source, Func<T, T> selector)
    where T : class
{
    yield return source;
    var parent = selector(source);
    if (parent == null)
        yield break;
    yield return SelectNestedParents(parent, selector).FirstOrDefault();
}

用法

var list = myObject.SelectNested(x => x.Parent);

问题

它几乎起作用了。但它只访问2个对象。它是自己和父母。

因此给出了从c开始的图c -> b -> a。返回了c, b,这不是我想要的。

我正在寻找的结果是b, c

遍历对象图并返回访问节点的递归yield方法

SelectNested的最后一行中,您只返回第一个父级:

yield return SelectNestedParents(parent, selector).FirstOrDefault();

您必须返回所有家长:

foreach (var p in SelectNestedParents(parent, selector))
  return p;

不使用递归,您可以使用迭代,这可能更有效:

public static IEnumerable<T> SelectNested<T>(this T source, Func<T, T> selector)
  where T : class {
  var current = source;
  while (current != null) {
    yield return current;
    current = selector(current);
  }
}

以下代码应按预期工作:

public static IEnumerable<T> SelectNested<T>()
{
    if (source != null){
        yield return source;
        var parent = selector(source);
        // Result of the recursive call is IEnumerable<T>
        // so you need to iterate over it and return its content.
        foreach (var parent in (SelectNested(selector(source))))
        {
            yield return parent;
        }
    }
}

严格来说,您的类看起来是一个列表,而不是一个图,因为selector只返回一个对象,而不是它们的枚举。因此递归是不必要的。

    public static IEnumerable<T> SelectNested<T>(this T source, Func<T, T> selector)
        where T : class
    {
        while (source != null)
        {
            yield return source;
            source = selector(source);
        }
    }