Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

This is an equivalent in a for-loop

for (IEnumerator i = Items.GetEnumerator(); i.MoveNext(); )
{
    Item item = (Item)i.Current;
    // some stuff
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top