分层 class 的迭代器

Iterator for hierarchical class

我有一个 C# class 来定义层次结构(比下面的示例复杂得多)。 class 有一个 Parent 并且可能 Children 是同一个 class。

我正在尝试为顶级对象编写一个迭代器,它将允许我访问 foreach 循环中的所有内容。

class Node
{
    public Node Parent { get; private set; }
    public bool HasParent { get { return (Parent != null); } }
    public string Name { get; private set; }
    public bool IsAnimal { get; set; }
    public bool IsCar { get; set; }
    public List<Node> Children { get; private set; }
    public bool HasChildren { get { return (Children != null); } }

}

想这样访问:

foreach (Node myNode in TopNode.Contents)

最好有多个迭代器来遍历不同类型的Children,例如:

foreach (Node myNode in TopNode.Animals)

foreach (Node myNode in TopNode.Cars)

将此方法添加到 Node class:

public IEnumerable<Node> DescendantsAndSelf()
{
    yield return this;
    if (Children != null) {
        foreach (Node child in Children) {
            foreach (Node node in child.DescendantsAndSelf()) {
                yield return node;
            }
        }
    }
}

并且您不需要针对不同类型的节点使用不同的迭代器。只需使用 .Where(...)

var allAnimals = myTopNode.DescendantsAndSelf()
    .Where(n => n.IsAnimal);

如果您牢记@LasseVågsætherKarlsen 的建议并从抽象基础 class Node 中派生出不同的节点类型,那么您可以将动物类型设为 Animal,如下所示:

IEnumerable<Animal> allAnimals = myTopNode.DescendantsAndSelf()
    .OfType<Animal>();

您也可以将 Children 声明为:

public List<Node> Children { get; } = new List<Node>();

像这样,Children 永远不会为空,HasChildren 将实现为:

public bool HasChildren => Children.Count > 0;

参见: