Is it possible to write recursive IEnumerable <T>
I have a class like:
class Spline int ChildrenCount; Spline GetChild (int index) class SplineCollection : IEnumerable<Spline> Spline Master Is it possible to write a recursive IEnumerable for a SplineCollection where it will return all children one by one?
EDIT: So, Master is the root box, and the hierarchy of her children can be any depth.
EDIT: using the name Box, I think I confused some people. It should be a geometric object, not a container. So change it to spline.
This will take the first step in crossing the Box tree. Then you can simply call this method in the Master field to return all recursive children.
public class Box { // ... public IEnumerable<Box> GetBoxes() { yield return this; for (int i=0; i<box.ChildrenCount; i++) { foreach (Box child in box.GetChild(i).GetBoxes()) { yield return child; } } } } I would go with manual stack maintenance instead of relying on the call stack here. The reason is that every time you visit Spline you had to create a new IEnumerable<Spline> if you were to use a call stack by recursively calling a method that gets children. That would be inefficient. You can greatly improve bypass using your own stack.
public IEnumerable<Spline> Descendants { get { // This performs a simple iterative preorder traversal. var stack = new Stack<Spline>(new Spline[] { this }); while (stack.Count > 0) { Spline current = stack.Pop(); yield return current; for (int i = current.ChildrenCount - 1; i >= 0; i--) { stack.Push(current.GetChild(i)); } } } } class Box { int ChildrenCount; Box GetChild (int index){/* some implementation*/} public IEnumerable<Box> Children { get { for(int i = 0; i != ChildrenCount; ++i) yield return GetChild(i); } } public IEnumerable<Box> Descendants { get { foreach(Box child in Children) { yield return child; foreach(Box desc in child.Descendants) yield return desc; } } } } You can call this from BoxCollection, but since Box is already a collection of boxes, I donโt see what the purpose of BoxCollection is here. In this case, using Box IEnumerable<Box> or one of its descendants ( ICollection<Box> , IList<Box> ) is likely to improve the utility.
It is also possible to do this in iterative rather than recursive mode, which sometimes has better performance (almost anytime the compiler does not turn recursion into interation), but recursive readability is more understandable and usually more than enough executors.
Yes, but you have to list the recursive result. You cannot just return it because the type does not match.
IEnumerable<int> Triangle(int n) { yield return n; if (n > 0) foreach (var e in Triangle(n - 1)) yield return e; } This adds to Brian Gideon's great answer, providing really only descendants, without a root element. In addition, it uses foreach , which may be available, for example, in the context of EF.
Here is my code ():
/// <summary> /// Retrieves all descendants. /// </summary> public IEnumerable<Item> Descendants { get { // This performs a simple iterative preorder traversal. Stack<Item> stack = new Stack<Item>(this.Children); while (stack.Count > 0) { Itemcurrent = stack.Pop(); yield return current; //Push current children foreach (Item currentChild in current.Children) { stack.Push(currentChild); } } } } Of course. You donโt even need a BoxContainer, since there is a container as a container by whose name:
public class Box { private List<Box> myBoxes; public IEnumerable<Box> GetAllBoxes() { yield return this; foreach (var box in myBoxes) { var enumerator = box.GetAllBoxes().GetEnumerator(); while(enumerator.MoveNext()) yield return enumerator.Current; } } } If in box A, placed in boxes B and C, in box B, boxes D and E were placed, and in box F with box F, the enumeration will be issued A, B, D, E, C, F.