Question about IEnumerable and Interface Signatures

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

    Question about IEnumerable and Interface Signatures

    In the code below from MSDN

    How do the PeopleEnum methods ever get called?

    foreach (Person p in peopleList)
    Console.WriteLi ne(p.firstName + " " + p.lastName);

    What is going on behind the scenes in the foreach?

    Also, I could not find where the interface signatures were for the
    IEnumerable and IEnumerator. How did they know what methods they were
    required to use from the interface signature. I looked them up on
    MSDN, but didn't see any references to GetEnumerator or MoveNext.
    Just this type explanation:

    [ComVisibleAttri bute(true)]
    [GuidAttribute(" 496B0ABF-CDEE-11d3-88E8-00902754C43A")]
    public interface IEnumerator

    Exposes an enumerator, which supports a simple iteration over a non-generic collection.


    Thanks.

    ---
    using System;
    using System.Collecti ons;

    public class Person
    {
    public Person(string fName, string lName)
    {
    this.firstName = fName;
    this.lastName = lName;
    }

    public string firstName;
    public string lastName;
    }

    public class People : IEnumerable
    {
    private Person[] _people;
    public People(Person[] pArray)
    {
    _people = new Person[pArray.Length];

    for (int i = 0; i < pArray.Length; i++)
    {
    _people[i] = pArray[i];
    }
    }

    public IEnumerator GetEnumerator()
    {
    return new PeopleEnum(_peo ple);
    }
    }

    public class PeopleEnum : IEnumerator
    {
    public Person[] _people;

    // Enumerators are positioned before the first element
    // until the first MoveNext() call.
    int position = -1;

    public PeopleEnum(Pers on[] list)
    {
    _people = list;
    }

    public bool MoveNext()
    {
    position++;
    return (position < _people.Length) ;
    }

    public void Reset()
    {
    position = -1;
    }

    public object Current
    {
    get
    {
    try
    {
    return _people[position];
    }
    catch (IndexOutOfRang eException)
    {
    throw new InvalidOperatio nException();
    }
    }
    }
    }

    class App
    {
    static void Main()
    {
    Person[] peopleArray = new Person[3]
    {
    new Person("John", "Smith"),
    new Person("Jim", "Johnson"),
    new Person("Sue", "Rabon"),
    };

    People peopleList = new People(peopleAr ray);
    foreach (Person p in peopleList)
    Console.WriteLi ne(p.firstName + " " + p.lastName);

    }
    }

    /* This code produces output similar to the following:
    *
    * John Smith
    * Jim Johnson
    * Sue Rabon
    *
    */
  • Jon Skeet [C# MVP]

    #2
    Re: Question about IEnumerable and Interface Signatures

    On Jun 12, 5:01 pm, jmDesktop <needin4mat...@ gmail.comwrote:
    In the code below from MSDN
    >
    How do the PeopleEnum methods ever get called?
    >
    foreach (Person p in peopleList)
    Console.WriteLi ne(p.firstName + " " + p.lastName);
    >
    What is going on behind the scenes in the foreach?
    foreach calls GetEnumerator() on the IEnumerable to get an
    IEnumerator, then calls MoveNext() and Current on the IEnumerator,
    executing the body of the loop each time, until MoveNext() returns
    false or the body of the foreach loop exits early somehow (break/
    return/exception).

    It then (irrespective of whether it reached the end or not) checks
    whether or not the IEnumerator implements IDisposable, and calls
    Dispose if so. (The generic IEnumerator<Tin terface extends
    IDisposable, so if there's a generic IEnumerable<Tth e compiler
    doesn't need to perform an execution-time check here - it just calls
    Dispose.)
    Also, I could not find where the interface signatures were for the
    IEnumerable and IEnumerator. How did they know what methods they were
    required to use from the interface signature. I looked them up on
    MSDN, but didn't see any references to GetEnumerator or MoveNext.
    The interfaces IEnumerable and IEnumerator are both defined in the
    System.Collecti ons namespace, and the methods within them are
    documented in MSDN in the normal way. The generic forms are in the
    System.Collecti ons.Generic namespace.

    In fact, the C# compiler can use foreach without implementing
    IEnumerable and IEnumerator at all - but it's extremely rare.

    Jon

    Comment

    • =?Utf-8?B?U3VqZWV0?=

      #3
      RE: Question about IEnumerable and Interface Signatures

      Rather that explaining here what happens, I would suggest you compile the
      code and open the assembly in ildasm.exe to exactly see what the compiler
      does behind the scenes. Thats the best way IMO to know.

      Sujeet

      "jmDesktop" wrote:
      In the code below from MSDN
      >
      How do the PeopleEnum methods ever get called?
      >
      foreach (Person p in peopleList)
      Console.WriteLi ne(p.firstName + " " + p.lastName);
      >
      What is going on behind the scenes in the foreach?
      >
      Also, I could not find where the interface signatures were for the
      IEnumerable and IEnumerator. How did they know what methods they were
      required to use from the interface signature. I looked them up on
      MSDN, but didn't see any references to GetEnumerator or MoveNext.
      Just this type explanation:
      >
      [ComVisibleAttri bute(true)]
      [GuidAttribute(" 496B0ABF-CDEE-11d3-88E8-00902754C43A")]
      public interface IEnumerator
      >
      Exposes an enumerator, which supports a simple iteration over a non-generic collection.

      >
      Thanks.
      >
      ---
      using System;
      using System.Collecti ons;
      >
      public class Person
      {
      public Person(string fName, string lName)
      {
      this.firstName = fName;
      this.lastName = lName;
      }
      >
      public string firstName;
      public string lastName;
      }
      >
      public class People : IEnumerable
      {
      private Person[] _people;
      public People(Person[] pArray)
      {
      _people = new Person[pArray.Length];
      >
      for (int i = 0; i < pArray.Length; i++)
      {
      _people[i] = pArray[i];
      }
      }
      >
      public IEnumerator GetEnumerator()
      {
      return new PeopleEnum(_peo ple);
      }
      }
      >
      public class PeopleEnum : IEnumerator
      {
      public Person[] _people;
      >
      // Enumerators are positioned before the first element
      // until the first MoveNext() call.
      int position = -1;
      >
      public PeopleEnum(Pers on[] list)
      {
      _people = list;
      }
      >
      public bool MoveNext()
      {
      position++;
      return (position < _people.Length) ;
      }
      >
      public void Reset()
      {
      position = -1;
      }
      >
      public object Current
      {
      get
      {
      try
      {
      return _people[position];
      }
      catch (IndexOutOfRang eException)
      {
      throw new InvalidOperatio nException();
      }
      }
      }
      }
      >
      class App
      {
      static void Main()
      {
      Person[] peopleArray = new Person[3]
      {
      new Person("John", "Smith"),
      new Person("Jim", "Johnson"),
      new Person("Sue", "Rabon"),
      };
      >
      People peopleList = new People(peopleAr ray);
      foreach (Person p in peopleList)
      Console.WriteLi ne(p.firstName + " " + p.lastName);
      >
      }
      }
      >
      /* This code produces output similar to the following:
      *
      * John Smith
      * Jim Johnson
      * Sue Rabon
      *
      */
      >

      Comment

      • =?Utf-8?B?U3VqZWV0?=

        #4
        Re: Question about IEnumerable and Interface Signatures

        Adding to what John said, specifically for foreach statement the 'peopleList'
        type does not have to implement IEnumearble. It can also just have a method
        GetEnumerator() that returns a type Person that has a public instance
        'MoveNext()' method that returns a bool and a public instance property
        'Current' that returns the type 'Person'

        But IMO implementing IEnumerable explicitly is more cleaner and easy to read.

        Sujeet

        "Jon Skeet [C# MVP]" wrote:
        On Jun 12, 5:01 pm, jmDesktop <needin4mat...@ gmail.comwrote:
        In the code below from MSDN

        How do the PeopleEnum methods ever get called?

        foreach (Person p in peopleList)
        Console.WriteLi ne(p.firstName + " " + p.lastName);

        What is going on behind the scenes in the foreach?
        >
        foreach calls GetEnumerator() on the IEnumerable to get an
        IEnumerator, then calls MoveNext() and Current on the IEnumerator,
        executing the body of the loop each time, until MoveNext() returns
        false or the body of the foreach loop exits early somehow (break/
        return/exception).
        >
        It then (irrespective of whether it reached the end or not) checks
        whether or not the IEnumerator implements IDisposable, and calls
        Dispose if so. (The generic IEnumerator<Tin terface extends
        IDisposable, so if there's a generic IEnumerable<Tth e compiler
        doesn't need to perform an execution-time check here - it just calls
        Dispose.)
        >
        Also, I could not find where the interface signatures were for the
        IEnumerable and IEnumerator. How did they know what methods they were
        required to use from the interface signature. I looked them up on
        MSDN, but didn't see any references to GetEnumerator or MoveNext.
        >
        The interfaces IEnumerable and IEnumerator are both defined in the
        System.Collecti ons namespace, and the methods within them are
        documented in MSDN in the normal way. The generic forms are in the
        System.Collecti ons.Generic namespace.
        >
        In fact, the C# compiler can use foreach without implementing
        IEnumerable and IEnumerator at all - but it's extremely rare.
        >
        Jon
        >

        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: Question about IEnumerable and Interface Signatures

          Sujeet <Sujeet@discuss ions.microsoft. comwrote:
          Adding to what John said, specifically for foreach statement the 'peopleList'
          type does not have to implement IEnumearble. It can also just have a method
          GetEnumerator() that returns a type Person that has a public instance
          'MoveNext()' method that returns a bool and a public instance property
          'Current' that returns the type 'Person'
          >
          But IMO implementing IEnumerable explicitly is more cleaner and easy to read.
          Agreed - although I'd implement IEnumerable<Per sonand do it with an
          iterator block :)

          --
          Jon Skeet - <skeet@pobox.co m>
          Web site: http://www.pobox.com/~skeet
          Blog: http://www.msmvps.com/jon.skeet
          C# in Depth: http://csharpindepth.com

          Comment

          Working...