Re: foreach pretty useless for composite classes, don't ya thunk?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Peter Morris

    Re: foreach pretty useless for composite classes, don't ya thunk?

    I am not sure what you are asking. You seem to be asking how to implement a
    plain IEnumerable on a composite structure, but then your example shows a
    flat structure using "yield". Your subject makes me infer that you think
    foreach is enirely useless for composite structures.

    I will address the subject text, because that makes the most sense to me :-)
    Take the following class

    public class MyTreeNode : IEnumerable<MyT reeNode>
    {
    public readonly List<MyTreeNode ChildNodes = new List<MyTreeNode >();
    public readonly string Name;
    public MyTreeNode ParentNode { get; private set; }

    public MyTreeNode(MyTr eeNode parentNode, string name)
    {
    ParentNode = parentNode;
    Name = name;
    if (parentNode != null)
    ParentNode.Chil dNodes.Add(this );
    }

    public string FullName
    {
    get
    {
    if (ParentNode == null)
    return Name;
    else
    return ParentNode.Full Name + "/" + Name;
    }
    }

    public IEnumerator<MyT reeNodeGetEnume rator()
    {
    foreach (var node in ChildNodes)
    {
    yield return node;
    foreach (var subNode in node)
    yield return subNode;
    }
    }

    IEnumerator IEnumerable.Get Enumerator()
    {
    return GetEnumerator() ;
    }
    }
    }


    it can be used like so....


    class Program
    {
    static void Main(string[] args)
    {
    var tree = new MyTreeNode(null , "Root");
    AddChildNodes(t ree, 1, 3);

    //********
    //NOTE: Foreach not being pretty useless on a composite structure
    //********
    foreach (var node in tree)
    {
    Console.WriteLi ne(node.FullNam e);
    }
    Console.ReadLin e();
    }

    static void AddChildNodes(M yTreeNode node, int level, int maxLevel)
    {
    string[] names = new string[] { "A", "B", "C"};
    foreach (var name in names)
    {
    var childNode = new MyTreeNode(node , name);
    if (level < maxLevel)
    AddChildNodes(c hildNode, level + 1, maxLevel);
    }

    }
    }


    and it will output the following.....

    Root/A
    Root/A/A
    Root/A/A/A
    Root/A/A/B
    Root/A/A/C
    Root/A/B
    Root/A/B/A
    Root/A/B/B
    Root/A/B/C
    Root/A/C
    Root/A/C/A
    Root/A/C/B
    Root/A/C/C
    Root/B
    Root/B/A
    Root/B/A/A
    Root/B/A/B
    Root/B/A/C
    Root/B/B
    Root/B/B/A
    Root/B/B/B
    Root/B/B/C
    Root/B/C
    Root/B/C/A
    Root/B/C/B
    Root/B/C/C
    Root/C
    Root/C/A
    Root/C/A/A
    Root/C/A/B
    Root/C/A/C
    Root/C/B
    Root/C/B/A
    Root/C/B/B
    Root/C/B/C
    Root/C/C
    Root/C/C/A
    Root/C/C/B
    Root/C/C/C


    Does that prove that foreach is useful for composite structures, or have I
    completely missed the point of what you were trying to say?



    Regards

    Pete


  • raylopez99

    #2
    Re: foreach pretty useless for composite classes, don't ya thunk?

    On Sep 20, 4:14 am, "Peter Morris" <mrpmorri...@SP AMgmail.comwrot e:
    >
    Does that prove that foreach is useful for composite structures, or have I
    completely missed the point of what you were trying to say?
    >
    Thanks; this was a good example that I've saved to study. Seems a
    couple of things are new to me (I've never seen readonly for a list,
    only for primitive data like an int, but I guess it makes sense;
    likewise 'var' sounds like Visual Basic but it's C#3 compliant I
    think), but the main point is that for a "composite" structure (where
    I take it a class contains another class as member) uses 'foreach' but
    implicitly uses the properties of collections themselves for the
    member variable.

    To wit:

    public IEnumerator<MyT reeNodeGetEnume rator()
    {
    foreach (var node in ChildNodes)
    {
    yield return node;
    foreach (var subNode in node)
    yield return subNode;
    }
    }

    makes use of the property of public readonly List<MyTreeNode >
    ChildNodes = new List<MyTreeNode >();
    that "List" is a generic container that has its own "behind the
    scenes" iterator.

    However, as I type this I see that two yield returns are present, but,
    I've seen this before and it's legal.

    Bottom line: foreach is a useful tool, and once I study this example
    more I'll have more to say perhaps, but it's not clear you are really
    using 'foreach' any different from the way I currently use it: to
    iterate member variables (even classes) that are parts of generic
    containers (from the collections library) like List<MyTreeNode >
    ChildNodes = new List<MyTreeNode >();

    Or maybe that's how you are supposed to use foreach, since these
    containers have 'foreach' built in, behind the scenes. Anyway more
    later.

    RL

    Comment

    • Peter Morris

      #3
      Re: foreach pretty useless for composite classes, don't ya thunk?

      couple of things are new to me (I've never seen readonly for a list,
      only for primitive data like an int, but I guess it makes sense;
      Just saves its reference from changing :-)

      likewise 'var' sounds like Visual Basic but it's C#3 compliant
      It's just shorthand for writing the class name out twice. I only use it
      where it is obvious what the type is.

      >However, as I type this I see that two yield returns are present, but,
      >I've seen this before and it's legal.
      yield return 1;
      yield return 3;
      yield return 5;
      yield return 7;

      That's legal too, but not much use :-)

      >>
      Bottom line: foreach is a useful tool, and once I study this example
      more I'll have more to say perhaps, but it's not clear you are really
      using 'foreach' any different from the way I currently use it:
      <<

      You *never* use "foreach" differently. "foreach" is just a language
      specific way of comsuming the iterator pattern, "yield" is a language
      specific way of implementing the iterator pattern. The purpose of the
      iterator pattern is to allow you to get access to all *relevant* items in
      turn, and not to worry about how those values are obtained. An example is
      to get each word within a document for spell checking; these words are held
      within various containers (a word, within a paragraph, within a cell, within
      a table row, within a table, within a column, within a page, within a
      document) - you wouldn't want to write code to loop through all of those,
      you just want to iterate all words within the document.
      >>
      Or maybe that's how you are supposed to use foreach, since these
      containers have 'foreach' built in, behind the scenes. Anyway more
      later.
      <<

      Yep. As I just said above, foreach is a consumer of the iterator pattern,
      nothing more.



      Pete

      Comment

      • raylopez99

        #4
        Re: foreach pretty useless for composite classes, don't ya thunk?

        OK, I am beginning to see now, thanks Peter Morris.

        But one more thing: can you tell me how to get rid of this compiler
        error?:

        foreach statement cannot operate on variables of type
        'IEnumerableEx0 1.Namer' because it implements multiple instantiations
        of System.Collecti ons.Generic.IEn umerable<T>'; try casting to a
        specific interface instantiation

        See the code I will post to Family Tree Mike's reply (since it's his
        code, modified).

        Almost there (for me), I appreciate it.

        BTW your example was good for a n-ary tree that is traversed 'depth
        first' recursively rather than 'breath first', and I've put it in my
        library as such; thanks again. I already have (from my own work) a
        'breath first' non-recursive n-ary tree, so this complements that.

        RL

        Peter Morris wrote:
        >
        Yep. As I just said above, foreach is a consumer of the iterator pattern,
        nothing more.

        Comment

        • Brian Gideon

          #5
          Re: foreach pretty useless for composite classes, don't ya thunk?

          On Sep 20, 4:16 pm, raylopez99 <raylope...@yah oo.comwrote:
          BTW your example was good for a n-ary tree that is traversed 'depth
          first' recursively rather than 'breath first', and I've put it in my
          library as such; thanks again.  I already have (from my own work) a
          'breath first' non-recursive n-ary tree, so this complements that.
          Exactly. And that leads to the next big advantage of the iterator/
          enumerator pattern. The collection class itself encapsulates the
          logic required to enumerate it's items.

          Comment

          Working...