Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IEnumerable , IEnumerator vs foreach, when to use what [duplicate]

Tags:

c#

enumeration

I was going through IEnumerable and IEnumerator , but could not get one point clearly..if we have foreach, then why do we need this two interfaces? Is there any scenario where we have to use interfaces.If yes, then can somebody explain with an example. Any suggestions and remarks are welcome. Thanks.

like image 483
Wondering Avatar asked Jul 06 '09 06:07

Wondering


People also ask

What is difference between IEnumerable and IEnumerator?

IEnumerable is an interface defining a single method GetEnumerator() that returns an IEnumerator interface. This works for readonly access to a collection that implements that IEnumerable can be used with a foreach statement. IEnumerator has two methods MoveNext and Reset. It also has a property called Current.

What is difference between IEnumerable and enumerable in C#?

IEnumerable- It is an Interface and Exposes the enumerator, which supports a simple iteration over a collection of a specified type. Enumerable- It is a class and Provides a set of static methods for querying objects that implement IEnumerable.

What does IEnumerator mean?

IEnumerator is an interface, which when implemented allows you to iterate through the list of controls. To implement it requires that you provide two methods - Reset to go back to the beginning of the list, and MoveNext to move forward, and Current to get the current item.

Is IEnumerator an interface?

IEnumerator is the base interface for all non-generic enumerators. Its generic equivalent is the System. Collections.


1 Answers

foreach uses the interfaces in many cases. You need the interfaces if you want to implement a sequence which foreach can then use. (Iterator blocks usually make this implementation task very simple though.)

However, just occasionally it can be useful to use the iterators directly. A good example is when trying to "pair up" two different sequences. For example, suppose you receive two sequences - one of names, one of ages, and you want to print the two together. You might write:

static void PrintNamesAndAges(IEnumerable<string> names, IEnumerable<int> ages) {     using (IEnumerator<int> ageIterator = ages.GetEnumerator())     {         foreach (string name in names)         {             if (!ageIterator.MoveNext())             {                 throw new ArgumentException("Not enough ages");             }             Console.WriteLine("{0} is {1} years old", name, ageIterator.Current);         }         if (ageIterator.MoveNext())         {             throw new ArgumentException("Not enough names");         }      } } 

Likewise it can be useful to use the iterator if you want to treat (say) the first item differently to the rest:

public T Max<T>(IEnumerable<T> items) {     Comparer<T> comparer = Comparer<T>.Default;      using (IEnumerator<T> iterator = items.GetEnumerator())     {         if (!iterator.MoveNext())         {             throw new InvalidOperationException("No elements");         }         T currentMax = iterator.Current;          // Now we've got an initial value, loop over the rest         while (iterator.MoveNext())         {             T candidate = iterator.Current;             if (comparer.Compare(candidate, currentMax) > 0)             {                 currentMax = candidate;             }         }         return currentMax;     } } 

Now, if you're interested in the difference between IEnumerator<T> and IEnumerable<T>, you might want to think of it in database terms: think of IEnumerable<T> as a table, and IEnumerator<T> as a cursor. You can ask a table to give you a new cursor, and you can have multiple cursors over the same table at the same time.

It can take a while to really grok this difference, but just remembering that a list (or array, or whatever) doesn't have any concept of "where you are in the list" but an iterator over that list/array/whatever does have that bit of state is helpful.

like image 133
Jon Skeet Avatar answered Sep 24 '22 08:09

Jon Skeet