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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?Utf-8?B?RmFtaWx5IFRyZWUgTWlrZQ==?=

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

    An example of a slightly more complicated class might be to have a collection
    of first names, and a collection of last names in your class. The
    IEnumerable functions then could return the complete set of all possible
    combinations of first and last name.


  • raylopez99

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

    On Sep 19, 4:56 am, Family Tree Mike
    <FamilyTreeM... @discussions.mi crosoft.comwrot e:
    An example of a slightly more complicated class might be to have a collection
    of first names, and a collection of last names in your class.  The
    IEnumerable functions then could return the complete set of all possible
    combinations of first and last name.
    What would be that example, FTM? The example I gave was from MDN and
    it in turn was from an earlier example (same author, he just didn't
    have the latter part "You can have the best of both worlds.."


    RL

    Comment

    • =?Utf-8?B?RmFtaWx5IFRyZWUgTWlrZQ==?=

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

      Sorry, I cannot think back how to do this in VS 2003.

      using System;
      using System.Collecti ons.Generic;
      using System.Linq;
      using System.Text;

      namespace NameGenerator
      {
      public class Namer : IEnumerable<str ing>
      {
      public string [ ] FirstNames;
      public string [ ] LastNames;

      IEnumerator<str ingIEnumerable< string>.GetEnum erator ()
      {
      for (int idxLast = 0; idxLast < LastNames.Count (); ++idxLast)
      for (int idxFirst = 0; idxFirst < FirstNames.Coun t (); ++idxFirst)
      yield return string.Format ( "{0} {1}",
      FirstNames [idxFirst], LastNames [idxLast] );
      }

      System.Collecti ons.IEnumerator
      System.Collecti ons.IEnumerable .GetEnumerator ()
      {
      for (int idxLast = 0; idxLast < LastNames.Count (); ++idxLast)
      for (int idxFirst = 0; idxFirst < FirstNames.Coun t (); ++idxFirst)
      yield return string.Format ( "{0} {1}",
      FirstNames [idxFirst], LastNames [idxLast] );
      }
      }


      class Program
      {
      static void Main ( string [ ] args )
      {
      Namer nlist = new Namer ();
      nlist.FirstName s = new string [ ] { "Ray", "Casey", "Zanaida" };
      nlist.LastNames = new string [ ] { "Anthony", "Gonzales", "Lopez",
      "Jones" };

      foreach (string s in nlist)
      Console.Out.Wri teLine ( string.Format ( "The next name is: {0}", s )
      );

      Console.In.Read Line ();
      }
      }
      }

      Comment

      • raylopez99

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

        On Sep 19, 10:51 am, Family Tree Mike
        <FamilyTreeM... @discussions.mi crosoft.comwrot e:
        An example of a slightly more complicated class might be to have a
        collection
        of first names, and a collection of last names in your class. The
        IEnumerable functions then could return the complete set of all
        possible
        combinations of first and last name

        ////////////

        Thanks FTM. I guess your program was to demonstrate the above. I
        appreciate it, but I note that essentially you can do the same thing
        with a simple call to a function that does a sort and so forth, at the
        cost of foregoing the 'foreach' notation.

        In any event, I'm not sure your code would work however, since I don't
        see any of the three required functions of IEnumerator--MoveNext,
        Resent, and Current.

        RL

        Comment

        • Brian Gideon

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

          On Sep 19, 1:19 pm, raylopez99 <raylope...@yah oo.comwrote:
          On Sep 19, 10:51 am, Family Tree Mike<FamilyTree M...@discussion s.microsoft.com wrote:
          >
          An example of a slightly more complicated class might be to have a
          collection
          of first names, and a collection of last names in your class.  The
          IEnumerable functions then could return the complete set of all
          possible
          combinations of first and last name
          >
          ////////////
          >
          Thanks FTM.  I guess your program was to demonstrate the above.  I
          appreciate it, but I note that essentially you can do the same thing
          with a simple call to a function that does a sort and so forth, at the
          cost of foregoing the 'foreach' notation.
          Just to make sure I understand what you're saying...you could create a
          function that generates a new collection whose elements are the result
          of the operation that figures out all possible combinations of the
          first and last name right?

          The disadvantage of that is that the entire operation has to complete
          before the caller can work with that new collection. If you choose to
          go down the IEnumerable/IEnumerator route then the caller could exit
          out of the foreach enumeration early and *before* the operation (to
          figure out the combinations of first and last name) has completed.
          >
          In any event, I'm not sure your code would work however, since I don't
          see any of the three required functions of IEnumerator--MoveNext,
          Resent, and Current.
          >
          You don't see them because 1) the yield keyword was used to instruct
          the compiler to create the IEnumerator automatically and 2) the
          foreach keyword was used to instruct the compiler to call those
          methods on IEnumerator automatically. Use ILDASM to examine to the
          resultant assembly.

          Comment

          • raylopez99

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

            On Sep 20, 4:03 pm, "Family Tree Mike"
            <FamilyTreeM... @ThisOldHouse.c omwrote:
            Change the code to look like this in your foreach within main:
            >
            foreach (string s in ((IEnumerable <string>)nlist) )
              Console.Out.Wri teLine(string.F ormat("The next name is: {0}", s));
            >
            foreach (int i in ((IEnumerable<i nt>)nlist))
              Console.Out.Wri teLine(string.F ormat("The next integer is: {0}", i));

            Thanks FTM, that worked.

            BTW, a minor aside, I notice that you 'repeat' GetEnumerator() ***
            (see below) rather than use the 'convention', that I've seen in some
            books, of this format (for the non-generic IEnumerator, which is
            required):

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

            But, when I tried this above 'convention' in your code, I could not
            compile it, in fact, IntelliSense would not even recognize
            GetEnumerator (!). So I wonder if you've come across this.
            However,it's not a big deal since I just use your convention and it
            works fine.

            Thanks again,

            RL

            ***

            System.Collecti ons.IEnumerator
            System.Collecti ons.IEnumerable .GetEnumerator( )
            {
            for (int idxLast = 0; idxLast < LastNames.Count (); idxLast
            +
            +)
            //BTW ++idxLast (made globally) also works fine, strangely enough
            for (int idxFirst = 0; idxFirst < FirstNames.Coun t();
            idxFirst++)
            yield return string.Format(" {0} {1}",
            FirstNames[idxFirst], lastNames[idxLast]);

            for (int i = 0; i < iArrNamer.Lengt h; i++)
            {
            yield return iArrNamer[i];
            }

            Comment

            • Family Tree Mike

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

              Yes, I have noted what you said too. I believe it is because the
              GetEnumerator()
              is not a callable thing. It is used from the foreach context as has been
              noted. You
              don't really call it from the code. Hopefully one of the other folks can
              explain the
              details of why the method itself isn't callable. I just found an example
              that I follow
              and have continued on the tradition, so to speak...

              "raylopez99 " <raylopez99@yah oo.comwrote in message
              news:fd0fcd95-025d-4f75-9700-73a9d3bbf340@y3 8g2000hsy.googl egroups.com...
              On Sep 20, 4:03 pm, "Family Tree Mike"
              <FamilyTreeM... @ThisOldHouse.c omwrote:
              Change the code to look like this in your foreach within main:
              >
              foreach (string s in ((IEnumerable <string>)nlist) )
              Console.Out.Wri teLine(string.F ormat("The next name is: {0}", s));
              >
              foreach (int i in ((IEnumerable<i nt>)nlist))
              Console.Out.Wri teLine(string.F ormat("The next integer is: {0}", i));

              Thanks FTM, that worked.

              BTW, a minor aside, I notice that you 'repeat' GetEnumerator() ***
              (see below) rather than use the 'convention', that I've seen in some
              books, of this format (for the non-generic IEnumerator, which is
              required):

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

              But, when I tried this above 'convention' in your code, I could not
              compile it, in fact, IntelliSense would not even recognize
              GetEnumerator (!). So I wonder if you've come across this.
              However,it's not a big deal since I just use your convention and it
              works fine.

              Thanks again,

              RL

              ***

              System.Collecti ons.IEnumerator
              System.Collecti ons.IEnumerable .GetEnumerator( )
              {
              for (int idxLast = 0; idxLast < LastNames.Count (); idxLast
              +
              +)
              //BTW ++idxLast (made globally) also works fine, strangely enough
              for (int idxFirst = 0; idxFirst < FirstNames.Coun t();
              idxFirst++)
              yield return string.Format(" {0} {1}",
              FirstNames[idxFirst], lastNames[idxLast]);

              for (int i = 0; i < iArrNamer.Lengt h; i++)
              {
              yield return iArrNamer[i];
              }

              Comment

              • raylopez99

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



                Brian Gideon wrote:
                >
                Instead of declaring multple GetEnumerator methods that return
                IEnumerator objects why not declare different methods with different
                names that return IEnumerable objects. When used in a member that
                returns an IEnumerable the yield keyword will cause the compiler to
                automatically generate an appropriate IEnumerable and IEnumerator
                combination. That's the general pattern I was referring to when I
                metioned the Dictionary.Valu es and Dictionary.Keys properties in
                another post.
                Like so many things in programming, without a specific example it's a
                no-go. Just tried various permuations and it won't work.

                If it's simple enough to show please show us.

                Otherwise I'll stick to FTM's convention, which works and is not an
                eyesore to me.

                RL

                Comment

                • Brian Gideon

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

                  On Sep 22, 2:48 am, raylopez99 <raylope...@yah oo.comwrote:
                  Brian Gideon wrote:
                  >
                  Instead of declaring multple GetEnumerator methods that return
                  IEnumerator objects why not declare different methods with different
                  names that return IEnumerable objects.  When used in a member that
                  returns an IEnumerable the yield keyword will cause the compiler to
                  automatically generate an appropriate IEnumerable and IEnumerator
                  combination.  That's the general pattern I was referring to when I
                  metioned the Dictionary.Valu es and Dictionary.Keys properties in
                  another post.
                  >
                  Like so many things in programming, without a specific example it's a
                  no-go.  Just tried various permuations and it won't work.
                  >
                  If it's simple enough to show please show us.
                  >
                  Otherwise I'll stick to FTM's convention, which works and is not an
                  eyesore to me.
                  >
                  RL
                  Understood. Here's the shortest possible example I could come up with
                  to demonstrate everything you want to do. That is...define iterators
                  that enumerate the constituent variables of a composite class 1)
                  individually and 2) together. Notice that I use the yield keyword in
                  the context of members that return IEnumerable instead of
                  IEnumerator. I think with this example you'll see the power and
                  elegance behind the IEnumerator/IEnumerable/foreach pattern.

                  class Program
                  {
                  static void Main(string[] args)
                  {
                  MyCollection a = new MyCollection();

                  foreach (string name in a.FirstOnly)
                  {
                  Console.WriteLi ne(name);
                  }

                  foreach (string name in a.LastOnly)
                  {
                  Console.WriteLi ne(name);
                  }

                  foreach (string name in a.Combination)
                  {
                  Console.WriteLi ne(name);
                  }
                  }
                  }

                  public class MyCollection
                  {
                  private string[] m_First = { "Brian", "Ray" };
                  private string[] m_Last = { "Gideon", "Lopez" };

                  public MyCollection()
                  {
                  }

                  public IEnumerable<str ingFirstOnly
                  {
                  get
                  {
                  foreach (string name in m_First)
                  {
                  yield return name;
                  }
                  }
                  }

                  public IEnumerable<str ingLastOnly
                  {
                  get
                  {
                  foreach (string name in m_Last)
                  {
                  yield return name;
                  }
                  }
                  }

                  public IEnumerable<str ingCombination
                  {
                  get
                  {
                  foreach (string first in m_First)
                  {
                  foreach (string last in m_Last)
                  {
                  yield return first + " " + last;
                  }
                  }
                  }
                  }
                  }

                  Comment

                  Working...