Reputation: 26517
Why in this example from MSDN, in GetEnumerator
method, PeopleEnum
returns 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 Array data type implements ICloneable interface, why msdn has copied pArray to _people by writing a for loop?
Upvotes: 2
Views: 802
Reputation: 1062600
It needs to return exactly IEnumerator
to properly implement the IEnumerable
interface. It is doing this using an "explicit interface implementation", so on the public API you see PeopleEnum
, but IEnumerable
is still happy
But in reality you would very rarely write an enumerator this way in C# 2.0 or above; you'd use an iterator block (yield return
). See C# in Depth chapter 6 (free chapter!).
For info, the reason that PeopleEnum
exists at all here is that this looks like a .NET 1.1 sample, where that is the only way to create a typed enumerator. In .NET 2.0 and above there is IEnumerable<T>
/ IEnumerator<T>
, which has a typed (via generics) .Current
.
In .NET 2.0 / C# 2.0 (or above) I would have simply:
public class People : IEnumerable<Person> {
/* snip */
public IEnumerator<Person> GetEnumerator() {
return ((IEnumerable<Person>)_people).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() { return _people.GetEnumerator();}
}
Upvotes: 3
Reputation: 69252
Types implementing IEnumerable require a method called GetEnumerator that returns an IEnumerator. In that example (which is pretty obsolete as of C# 2.0) there is an enumerator class PeopleEnum that implements IEnumerator. It's what's used internally by the C# foreach statement.
A more up to date example would look more like the following. Note there's no longer a need for a PeopleEnum class now that 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];
}
}
}
Upvotes: 2