Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the for/while equivalent of foreach?

I have a foreach loop that needs converting to a for or while loop. My loop looks like this:

foreach (Item item in Items)
{
    // some stuff
}

What is the equivalent for or while loop?

I think I need to use GetEnumerator to get an IEnumerator<Item>, but I don't know how to use it properly. Items isn't a list, otherwise I'd use indexing.

like image 948
Kendall Frey Avatar asked Aug 21 '12 15:08

Kendall Frey


2 Answers

In the simplest case(no disposing etc.) you can use:

var enumerator = Items.GetEnumerator();// `var` to take advantage of more specific return type
while(enumerator.MoveNext())
{
  Item item = enumerator.Current;
  ...
}

For the exact rules check the C# specification 8.8.4 The foreach statement.

A foreach statement of the form

foreach (V v in x) embedded-statement

is then expanded to:

{
  E e = ((C)(x)).GetEnumerator();
  try {
     V v;
     while (e.MoveNext()) {
        v = (V)(T)e.Current;
                embedded-statement
    }
  }
  finally {
     … // Dispose e
  }

}

(Quoted from the C# Language Specification Version 4.0)

The types using here are: "a collection type C, enumerator type E and element type T". E is the return type of GetEnumerator, and not necessarily IEnumerator<V> since foreach uses duck typing. The spec also describes a number of corner cases and how to infer these types, but those details are probably not relevant here.

In C# 5 the declaration of v will be moved into the while loop to get more intuitive closure semantics.

like image 156
CodesInChaos Avatar answered Sep 28 '22 09:09

CodesInChaos


If you're going to use a for loop, it generally means there's some way of quickly accessing the n-th item (usually an indexer).

for(int i = 0; i < Items.Count; i++)
{
  Item item = Items[i]; //or Items.Get(i) or whatever method is relevant.
  //...
}

If you're just going to access the iterator, you usually just want to use a foreach loop. If, however, you can't, this is usually the model that makes sense:

using(IEnumerator<Item> iterator = Items.GetEnumerator())
while(iterator.MoveNext())
{
  Item item = iterator.Current;
  //do stuff
}

you could, technically, do this in a for loop, but it would be harder because the construct just doesn't align well with this format. If you were to discuss the reason that you can't use a foreach loop we may be able to help you find the best solution, whether or not that involves using a for loop or not.

like image 39
Servy Avatar answered Sep 28 '22 08:09

Servy