Enumerator

T

Tony Johansson

Hi!

At the end is a complete short program listed.

If I do this statement
Stack<string>.Enumerator q = numbers.GetEnumerator();
I create a Enumerator that is called q in this example.
But enumerator is used when iterating through a collection for example by
using the foreach construction.

So my first simple question is why is it not possible to write foreach in
this way using q as an enumerator ???
This cause the compile that is listed after the foreach.
My qualified guess is because this enumerator q doesn't implement the
IEnumerable we can't use a foreach here. That is what the compile errror
says. I'm on the right track.
foreach(string s in q)
{
Console.WriteLine(s);
}
Error 1 foreach statement cannot operate on variables of type
'System.Collections.Generic.Stack<string>.Enumerator' because
'System.Collections.Generic.Stack<string>.Enumerator' does not contain a
public definition for 'GetEnumerator' F:\C#\ConsoleApplication3\Tester.cs 42
7 ConsoleApplication3

My second question is:
This foreach construction in main works fine and that is because this
numbers(Stack<T>) implement the IEnumerable interface.
Is that correct described of me!
foreach (string number in numbers)
{
Console.WriteLine(number);
}

public static void Main()
{
Stack<string> numbers = new Stack<string>();

numbers.Push("one");
numbers.Push("two");
numbers.Push("three");
numbers.Push("four");
numbers.Push("five");
Stack<string>.Enumerator q = numbers.GetEnumerator();

while (q.MoveNext())
Console.WriteLine(q.Current);

foreach (string number in numbers)
{
Console.WriteLine(number);
}

Console.WriteLine("Popping '{0}'", numbers.Pop());
Console.WriteLine("Peek at next: '{0}'", numbers.Peek());
Console.WriteLine("Popping '{0}'", numbers.Pop());
Console.WriteLine("Peek at next: '{0}'", numbers.Peek());
}

//Tony
 
R

Rudy Velthuis

Tony said:
So my first simple question is why is it not possible to write
foreach in this way using q as an enumerator ???

in

foreach(sometype a in b)

b is a collection of some sorts, i.e. something that implements
IEnumerable or IEnumerable<T> (i.e. a class that PROVIDES an
enumerator), not something that is an IEnumerator or IEnumerator<T>.

After all, the elements are in the collection, not in the enumerator.

--
Rudy Velthuis http://rvelthuis.de

"This country, with its institutions, belongs to the people who
inhabit it. Whenever they shall grow weary of the existing
government, they can exercise their constitutional right of
amending it, or exercise their revolutionary right to overthrow
it."
-- Abraham Lincoln
 
T

Tom Shelton

Hi!

At the end is a complete short program listed.

If I do this statement
Stack<string>.Enumerator q = numbers.GetEnumerator();
I create a Enumerator that is called q in this example.
But enumerator is used when iterating through a collection for example by
using the foreach construction.

So my first simple question is why is it not possible to write foreach in
this way using q as an enumerator ???
This cause the compile that is listed after the foreach.
My qualified guess is because this enumerator q doesn't implement the
IEnumerable we can't use a foreach here. That is what the compile errror
says. I'm on the right track.
foreach(string s in q)
{
Console.WriteLine(s);
}
Error 1 foreach statement cannot operate on variables of type
'System.Collections.Generic.Stack<string>.Enumerator' because
'System.Collections.Generic.Stack<string>.Enumerator' does not contain a
public definition for 'GetEnumerator' F:\C#\ConsoleApplication3\Tester.cs 42
7 ConsoleApplication3

Actually, it's because the Enumerator type doesn't contain a public definition
for GetEnumerator. The fact is an object doesn't actually have to implement
IEnumerable to work with foreach - it simply has to have a public
GetEnumerator method...
My second question is:
This foreach construction in main works fine and that is because this
numbers(Stack<T>) implement the IEnumerable interface.
Is that correct described of me!
foreach (string number in numbers)
{
Console.WriteLine(number);
}

public static void Main()
{
Stack<string> numbers = new Stack<string>();

numbers.Push("one");
numbers.Push("two");
numbers.Push("three");
numbers.Push("four");
numbers.Push("five");
Stack<string>.Enumerator q = numbers.GetEnumerator();

while (q.MoveNext())
Console.WriteLine(q.Current);

foreach (string number in numbers)
{
Console.WriteLine(number);
}

Console.WriteLine("Popping '{0}'", numbers.Pop());
Console.WriteLine("Peek at next: '{0}'", numbers.Peek());
Console.WriteLine("Popping '{0}'", numbers.Pop());
Console.WriteLine("Peek at next: '{0}'", numbers.Peek());
}

//Tony

While it's true that Stack<T> implements IEnumerable and IEnumerable<T> - the
main reason is that there is a publicaly accessible implementation of
GetEnumerator.

using System;
using System.Collections.Generic;

namespace ConsoleApplication67
{
class Program
{
static void Main ( string[] args )
{
NoIEnumerable enumerable = new NoIEnumerable();
foreach ( int i in enumerable )
{
Console.WriteLine ( i );
}
}
}

// No IEnumerable interface on this class - simply provides a public
// GetEnumerator that returns an IEnumerator.
class NoIEnumerable
{
private List<int> ints = new List<int> () { 1, 2, 3, 4, 5 };
public IEnumerator<int> GetEnumerator ()
{
return new Enumerator ( ints );
}


private class Enumerator : IEnumerator<int>
{
private IEnumerator<int> e;

public Enumerator ( IEnumerable<int> ints )
{
e = ints.GetEnumerator ();
}

public int Current
{
get { return e.Current; }
}


object System.Collections.IEnumerator.Current
{
get { return e.Current; }
}

public bool MoveNext ()
{
return e.MoveNext ();
}

public void Reset ()
{
e.Reset ();
}

public void Dispose ()
{
e.Dispose ();
GC.SuppressFinalize (this);
}


}

}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top