views:

1301

answers:

7

When looking at C# code, I often see patterns like this:

DataType[] items = GetSomeItems();
OtherDataType[] itemProps = new OtherDataType[items.Length];

int i = 0;
foreach (DataType item in items)
{
    // Do some stuff with item, then finally
    itemProps[i] = item.Prop;
    i++;
}

The for-loop iterates over the objects in items, but also keeping a counter (i) for iterating over itemProps as well. I personally don't like this extra i hanging around, and instead would probably do something like:

DataType[] items = GetSomeItems();
OtherDataType[] itemProps = new OtherDataType[items.Length];

for (int i = 0; i < items.Length; i++)
{
    // Do some stuff with items[i], then finally
    itemProps[i] = items[i].Prop;
}

Is there perhaps some benfit to the first approach I'm not aware of? Is this a result of everybody trying to use that fancy foreach (...) syntax? I'm interested in your opinions on this.

+2  A: 

In this case, I don't think so. Sometimes, though, the collection doesn't implement this[int index] but it does implement GetEnumerator(). In the latter case, you don't have much choice.

tvanfosson
+4  A: 

With i being outside the array then if would be available after the completion of the loop. If you wanted to count the number of items and the collection didn't provide a .Count or .UBound property then this could be useful.

Like you I would normally use the second method, looks much cleaner to me.

DilbertDave
+6  A: 

If you are using C# 3.0 that will be better;

OtherDataType[] itemProps = items.Select(i=>i.Prop).ToArray();
yapiskan
Nice - cleaner still.
DilbertDave
That's LINQ right?
Jason Lepack
or even (from item in items select item.prop).ToArray()
David Kemp
+1  A: 

Some data structures are not well suited for random access but can be iterated over very fast ( Trees, linked lists, etc ). So if you need to iterate over one of these but need a count for some reason, your doomed to go the ugly way...

Nicolas Repiquet
+1  A: 

Semantically they may be equivalent, but in fact using foreach over an enumerator gives the compiler more scope to optimise.

I don't remember all the arguments off the top of my head,but they are well covered in Effective C#, which is recommended reading.

Phil Nash
+1  A: 

foreach (DataType item in items) This foreach loop makes it crystal clear that you're iterating over all the DataType item of, well yes, items. Maybe it makes the code a little longer, but it's not a "bad" code. For the other for-loop, you need to check inside the brackets to have an idea for what this loop is used.

The problem with this example lies in the fact that you're iterating over two different arrays in the same time which we don't do that often.. so we are stuck between two strategies.. either we "hack a bit" the fancy-foreach as you call it or we get back on the old-not-so-loved for(int i = 0; i ...). (There are other ways than those 2, of course)

So, I think it's the Vim vs Emacs things coming back in your question with the For vs Foreach loop :) People who like the for(), will say this foreach is useless, might cause performance issues and is just big. People who prefere foreach will say something like, we don't care if there's two extra line if we can read the code and maintenance it easily.

Finally, the i is outside the scope first the first example and inside for the second.. reasons to that?! Because if you use the i outside of your foreach, I would have called differently. And, for my opinion, I prefer the foreach ways because you see immediately what is happening. You also don't have to think about if it's < or =. You know immediately that you are iterating over all the list, However, sadly, people will forget about the i++ at the end :D So, I say Vim!

+1  A: 

Lets not forget that some collections do not implement a direct access operator[] and that you have to iterate using the IEnumerable interface which is most easily accessed with foreach().

ADB