Why in this example (derived from msdn), in the GetEnumerator method, does the new PeopleEnum return an IEnumerator?

Why does this example from MSDN, in the method GetEnumerator

, PeopleEnum

return IEnumerator

?

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];
        }
    }
   //why??? 
   IEnumerator IEnumerable.GetEnumerator()
   {
       return (IEnumerator) GetEnumerator();
   }

   public PeopleEnum GetEnumerator()
   {
       return new PeopleEnum(_people);
   }
}

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

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

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

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

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

object IEnumerator.Current
{
    get
    {
        return Current;
    }
}

public Person Current
{
    get
    {
        try
        {
            return _people[position];
        }
        catch (IndexOutOfRangeException)
        {
            throw new InvalidOperationException();
        }
    }
}

      

UPDATE: BTW, if the Array datatype implements the ICloneable interface, why did msdn copy the pArray to _people by writing a for loop?

+2


a source to share


2 answers


For the correct implementation of the interface, IEnumerable

you must specify exactly IEnumerator

. It does this using an "explicit interface implementation", so you see in the public API PeopleEnum

, but IEnumerable

is still happy

But in reality, you would very rarely write an enumerator this way in C # 2.0 or higher; you have to use an iterator ( yield return

) block . See C # in depth , chapter 6 (free chapter!).

For information, the reason it PeopleEnum

exists at all here is because it looks like the .NET 1.1 sample, where this is the only way to create a typed enumerator. In .NET 2.0 and up, there is a IEnumerable<T>

/ IEnumerator<T>

which is typed (via generics) .Current

.



In .NET 2.0 / C # 2.0 (or higher) I would just:

public class People : IEnumerable<Person> {
    /* snip */
    public IEnumerator<Person> GetEnumerator() {
        return ((IEnumerable<Person>)_people).GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator() { return _people.GetEnumerator();}
}

      

+3


a source


Types that implement IEnumerable require the GetEnumerator method, which returns IEnumerator. In this example (which is quite outdated as in C # 2.0) there is an enumerator class PeopleEnum that implements IEnumerator. This is what is used internally by the C # foreach statement.

A more modern example would look like this. Note that there is now no need for the PeopleEnum class when C # supports iterators. Effectively the compiler does all the heavy lifting for you.



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];
        }
    }

   IEnumerator IEnumerable.GetEnumerator()
   {
       for (int i=0; i < _people.Length; i++) {
           yield return _people[i];
       }
   }
}

      

+2


a source







All Articles