I have a C# class to define a hierarchy (much more complicated than the example below). The class has a Parent
and possibly Children
of the same class.
I am trying to write an iterator for the top level object that will allow me to access all the contents in a foreach
loop.
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); } }
}
Want to access like this:
foreach (Node myNode in TopNode.Contents)
It would be nice to have multiple iterators to traverse different types of Children
like:
foreach (Node myNode in TopNode.Animals)
or
foreach (Node myNode in TopNode.Cars)
Add this method to the 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;
}
}
}
}
And you don't need different iterators for different types of nodes. Just use .Where(...)
var allAnimals = myTopNode.DescendantsAndSelf()
.Where(n => n.IsAnimal);
If you take to heart @LasseVågsætherKarlsen's suggestion and derive different nodes types from an abstract base class Node
, then you can get animals typed as Animal
like this:
IEnumerable<Animal> allAnimals = myTopNode.DescendantsAndSelf()
.OfType<Animal>();
You could also declare Children
as:
public List<Node> Children { get; } = new List<Node>();
Like this, Children
would never be null and HasChildren
would be implemented as:
public bool HasChildren => Children.Count > 0;
See: