45

It seems like the cool way of looping in C# and Java is to use foreach instead of C style for loops.

Is there a reason why I should prefer this style over the C style?

I'm particularly interested in these two cases, but please address as many cases as you need to explain your points.

  • I wish to perform an operation on each item in a list.
  • I am searching for an item in a list, and wish to exit when that item is found.
MedicineMan
  • 13,795
  • 30
  • 92
  • 137
  • 19
    Btw, "address at least these two cases at a minimum" really makes your question sound like homework :) Just in case you didn't realise... – Stuart Golodetz Dec 08 '10 at 01:05
  • 2
    See also http://stackoverflow.com/questions/365615/in-net-which-loop-runs-faster-for-or-foreach, http://stackoverflow.com/questions/1124753/for-vs-foreach-loop-in-c and http://stackoverflow.com/questions/4364469/which-is-faster-for-or-foreach-closed – adrianbanks Dec 08 '10 at 01:07
  • This question gets asked in all manner of forms all the time, and implied (e.g. someone suggests refactoring to the "cool way") even more often; but it's one of my favourite issues in programming. +1. – Karl Knechtel Dec 08 '10 at 01:17
  • We're talking about saving 10's of milliseconds on huge huge arrays. Dunno about you, but I've got way more productive items that I can change in the apps I work on than this. Can't believe this is being upvoted so much. – P.Brian.Mackey Dec 08 '10 at 01:20
  • 4
    @P.Brian.Mackey It's being upvoted precisely **because** the performance isn't a real concern here, which means we can talk about and explain style. Some people really just don't "get it". They spend so long wrestling with C and C++ that they actually forget that how they do loops in those languages isn't actually "natural" in any meaningful sense. (I describe it as a kind of brain damage, if only because sometimes you need that kind of rhetoric to get the point across). The OP is trying hard not to be judgmental and brings up an interesting style issue; IMHO that makes it a great question. – Karl Knechtel Dec 08 '10 at 01:25
  • 2
    @stuart hmm. I hadn't thought about the HW angle. EXTRA CREDIT FOR ANYONE THAT ANSWERS. +1 – MedicineMan Dec 08 '10 at 01:33
  • Not all Arrays start at zero: http://msdn.microsoft.com/en-us/library/x836773a.aspx –  Jan 21 '11 at 21:10
  • to previous commenter. Anyone who doesn't start their arrays with zero index is a damn fool – MedicineMan Apr 18 '14 at 18:14

18 Answers18

79

Imagine that you're the head chef for a restaurant, and you're all preparing a huge omelette for a buffet. You hand a carton of a dozen eggs to each of two of the kitchen staff, and tell them to get cracking, literally.

The first one sets up a bowl, opens the crate, grabs each egg in turn - from left to right across the top row, then the bottom row - breaking it against the side of the bowl and then emptying it into the bowl. Eventually he runs out of eggs. A job well done.

The second one sets up a bowl, opens the crate, and then dashes off to get a piece of paper and a pen. He writes the numbers 0 through 11 next to the compartments of the egg carton, and the number 0 on the paper. He looks at the number on the paper, finds the compartment labelled 0, removes the egg and cracks it into the bowl. He looks at the 0 on the paper again, thinks "0 + 1 = 1", crosses out the 0 and writes 1 on the paper. He grabs the egg from compartment 1 and cracks it. And so on, until the number 12 is on the paper and he knows (without looking!) that there are no more eggs. A job well done.

You'd think the second guy was a bit messed in the head, right?

The point of working in a high-level language is to avoid having to describe things in a computer's terms, and to be able to describe them in your own terms. The higher-level the language, the more true this is. Incrementing a counter in a loop is a distraction from what you really want to do: process each element.


Further to that, linked-list type structures can't be processed efficiently by incrementing a counter and indexing in: "indexing" means starting over counting from the beginning. In C, we can process a linked list that we made ourselves by using a pointer for the loop "counter" and dereferencing it. We can do this in modern C++ (and to an extent in C# and Java) using "iterators", but this still suffers from the indirectness problem.


Finally, some languages are high-enough level that the idea of actually writing a loop to "perform an operation on each item in a list" or "search for an item in a list" is appalling (in the same way that the head chef shouldn't have to tell the first kitchen staff member how to ensure that all the eggs are cracked). Functions are provided that set up that loop structure, and you tell them - via a higher-order function, or perhaps a comparison value, in the searching case - what to do within the loop. (In fact, you can do these things in C++, although the interfaces are somewhat clumsy.)

Karl Knechtel
  • 51,161
  • 7
  • 77
  • 117
  • 4
    I've been using it for a while elsewhere on the internet. :) I suppose I could add a bit about how the second guy is likely to have a panic attack if he decided to look for "egg #12" anyway and then realized there's no such slot in the carton. ;) – Karl Knechtel Dec 08 '10 at 01:34
  • 4
    +1 For the humor :-). @Karl Knechtel I am wondering what the analogy would look like for the EggIndexOutOfBoundsException and the necessary try catch :-). – Dave Dec 08 '10 at 10:38
  • 3
    Throwing an exception is a form of panic attack, of course. Some people panic in more predictable and defined ways than others :) I suppose that catching such an exception, in this case, amounts to the head chef having seen this before and having a therapist on speed-dial, while not being willing to teach the guy how to do it "normally" (or just fire him). – Karl Knechtel Dec 08 '10 at 11:07
  • +1 This is a wonderful explanation of declarative programming. Well done! – Andrew Hare Dec 08 '10 at 15:33
  • @Andrew I usually think of it as functional programming, but "declarative" is quite possibly more accurate. – Karl Knechtel Dec 08 '10 at 16:10
  • I use a high level language to short-hand what I want. I don't need to know the exact instructions, but I want to know the gist of what it does behind the scenes. But otherwise nice explanation. – Bengie Dec 08 '10 at 17:29
  • "In fact, you can do these things in C++, although the interfaces are somewhat clumsy." Not any more: http://en.wikipedia.org/wiki/C%2B%2B0x#Range-based_for-loop – Ben Dec 13 '10 at 20:35
  • @Ben "these things" in that context refers to using higher-order functions - things that are called `map` and `reduce` in some other languages, and spelled more like `std::for_each` and `std::accumulate` in C++. It is nice to be able to do direct iteration (and without explicit iterator manipulation) in C++0x, though, yes. – Karl Knechtel Dec 13 '10 at 20:39
  • 1
    However For is efficient than foreach which is not true in your example. – Shrivallabh Apr 23 '14 at 09:30
73

Two major reasons I can think of are:

1) It abstracts away from the underlying container type. This means, for example, that you don't have to change the code that loops over all the items in the container when you change the container -- you're specifying the goal of "do this for every item in the container", not the means.

2) It eliminates the possibility of off-by-one errors.

In terms of performing an operation on each item in a list, it's intuitive to just say:

for(Item item: lst)
{
  op(item);
}

It perfectly expresses the intent to the reader, as opposed to manually doing stuff with iterators. Ditto for searching for items.

Stuart Golodetz
  • 19,132
  • 3
  • 45
  • 79
  • 8
    +1 for off-by-one errors. And congratulations on your second nice answer badge. – John Dec 08 '10 at 04:32
  • and it eliminates the forgot to progress or writing wrong halt condition (off by one is a single case for that). – none Dec 08 '10 at 10:12
37
  • foreach is simpler and more readable

  • It can be more efficient for constructions like linked lists

  • Not all collections support random access; the only way to iterate a HashSet<T> or a Dictionary<TKey, TValue>.KeysCollection is foreach.

  • foreach allows you to iterate through a collection returned by a method without an extra temporary variable:

    foreach(var thingy in SomeMethodCall(arguments)) { ... }
    
SLaks
  • 800,742
  • 167
  • 1,811
  • 1,896
  • 4
    +1 -- for pointing out that 'foreach' works with an *iterator* and not an indexed fetch. –  Dec 08 '10 at 01:05
  • Well, technically, "thingy" is your temporary variable - just defined within the scope of your loop =) – bitxwise Dec 08 '10 at 03:10
  • 2
    @bitxwise: No; `thingy` corresponds to `i`. A `for` loop would require _2_ temporaries. (clarified) – SLaks Dec 08 '10 at 03:15
  • 2
    I see you added "extra", which makes more sense. Regardless that thingy corresponds to i, both are still temporary variables. Your original answer only specified that a temporary variable (no "extra") was not necessary with a foreach. And even still, you can reference myCollection[i], alleviating the syntactic need for an additional temporary variable (not that I recommend it). Either way, let's not get into an elitist discussion over semantics. Cheers. – bitxwise Dec 08 '10 at 03:46
  • 1
    @bitwise - The extra variable is myCollection. In a foreach loop you don't need to put the method return value into a variable. – OrangeDog Dec 08 '10 at 09:57
19

One benefit for me is that it's less easy to make mistakes such as

    for(int i = 0; i < maxi; i++) {
        for(int j = 0; j < maxj; i++) {
...
        }
    }

UPDATE: This is one way the bug happens. I make a sum

int sum = 0;
for(int i = 0; i < maxi; i++) {
    sum += a[i];
}

and then decide to aggregate it more. So I wrap the loop in another.

int total = 0;
for(int i = 0; i < maxi; i++) {
   int sum = 0;
    for(int i = 0; i < maxi; i++) {
        sum += a[i];
    }
    total += sum;
}

Compile fails, of course, so we hand edit

int total = 0;
for(int i = 0; i < maxi; i++) {
   int sum = 0;
    for(int j = 0; j < maxj; i++) {
        sum += a[i];
    }
    total += sum;
}

There are now at least TWO mistakes in the code (and more if we've muddled maxi and maxj ) which will only be detected by runtime errors. And if you don't write tests... and it's a rare piece of code - this will bite someone ELSE - badly.

That is why it's a good idea to extract the inner loop into a method:

int total = 0;
for(int i = 0; i < maxi; i++) {
    total += totalTime(maxj);
}

private int totalTime(int maxi) {
   int sum = 0;
    for(int i = 0; i < maxi; i++) {
        sum += a[i];
    }
    return sum;
}

and it's more readable.

peter.murray.rust
  • 35,191
  • 41
  • 141
  • 211
16

foreach will perform identically to a for in all scenarios[1], including straightforward ones such as you describe.

However, foreach has certain non-performance-related advantages over for:

  1. Convenience. You do not need to keep an extra local i around (which has no purpose in life other than facilitating the loop), and you do not need to fetch the current value into a variable yourself; the loop construct has already taken care of that.
  2. Consistency. With foreach, you can iterate over sequences which are not arrays with the same ease. If you want to use for to loop over a non-array ordered sequence (e.g. a map/dictionary) then you have to write the code a little differently. foreach is the same in all cases it covers.
  3. Safety. With great power comes great responsibility. Why open opportunities for bugs related to incrementing the loop variable if you don't need it in the first place?

So as we see, foreach is "better" to use in most situations.

That said, if you need the value of i for other purposes, or if you are handling a data structure that you know is an array (and there is an actual specific reason for it being an array), the increased functionality that the more down-to-the-metal for offers will be the way to go.

[1] "In all scenarios" really means "all scenarios where the collection is friendly to being iterated", which would actually be "most scenarios" (see comments below). I really think that an iteration scenario involving an iteration-unfriendly collection would have to be engineered, however.

Jon
  • 396,160
  • 71
  • 697
  • 768
  • 1
    Whether or not *"`foreach` will perform identically to a `for` in all scenarios"* is an implementation detail of whatever collection type you happen to be traversing. It's certainly not guaranteed in any way, although I'd be surprised if there was ever a dramatic performance difference between the two of them. – LukeH Dec 08 '10 at 01:19
  • Technically I think the correct phrasing for my intent would be *"in all scenarios involving sequences which can be iterated over in O(n)"*. In practice, however, I don't think the writer of any collection class would expose an iteration interface that performed worse than O(n); hence my choice of expression. – Jon Dec 08 '10 at 01:23
  • This is a well written answer that should be upvoted because the formatting makes clear what the key points are. – MedicineMan Dec 08 '10 at 01:43
  • @MedicineMan: Formatting helps a lot, but it is not a reason to upvote; content is what counts. – Lawrence Dol Dec 08 '10 at 05:06
  • 1
    +1, but: "the increased functionality that the more down-to-the-metal for offers will be the way to go." Only if you **have a use for** that functionality. – Karl Knechtel Dec 08 '10 at 11:09
  • @Karl: Maybe the writing isn't very good, but that is what I think I 'm saying in the first half of the sentence you quote. :) – Jon Dec 08 '10 at 15:14
  • I got distracted from the bit at the start by the bit in the middle. Disturbing, because I'm accustomed to writing sentences longer than that and deeming them perfectly comprehensible. :/ – Karl Knechtel Dec 08 '10 at 16:08
10

You should probably consider also LINQ if you are targeting C# as a language, since this is another logical way to do loops.

By perform an operation on each item in a list do you mean modify it in place in the list, or simply do something with the item (e.g. print it, accumulate it, modify it, etc.)? I suspect it is the latter, since foreach in C# won't allow you to modify the collection you are looping over, or at least not in a convenient way...

Here are two simple constructs, first using forand then using foreach, which visit all strings in a list and turn them into uppercase strings:

List<string> list = ...;
List<string> uppercase = new List<string> ();
for (int i = 0; i < list.Count; i++)
{
    string name = list[i];
    uppercase.Add (name.ToUpper ());
}

(note that using the end condition i < list.Count instead of i < length with some precomputer length constant is considered a good practice in .NET, since the compiler would anyway have to check for the upper bound when list[i] is invoked in the loop; if my understanding is correct, the compiler is able in some circumstances to optimize away the upper bound check it would normally have done).

Here is the foreach equivalent:

List<string> list = ...;
List<string> uppercase = new List<string> ();
foreach (name in list)
{
    uppercase.Add (name.ToUpper ());
}

Note: basically, the foreach construct can iterate over any IEnumerable or IEnumerable<T> in C#, not just over arrays or lists. The number of elements in the collection might therefore not be known beforehand, or might even be infinite (in which case you certainly would have to include some termination condition in your loop, or it won't exit).

Here are a few equivalent solutions I can think of, expressed using C# LINQ (and which introduces the concept of a lambda expression, basically an inline function taking an x and returning x.ToUpper () in the following examples):

List<string> list = ...;
List<string> uppercase = new List<string> ();
uppercase.AddRange (list.Select (x => x.ToUpper ()));

Or with the uppercase list populated by its constructor:

List<string> list = ...;
List<string> uppercase = new List<string> (list.Select (x => x.ToUpper ()));

Or the same using the ToList function:

List<string> list = ...;
List<string> uppercase = list.Select (x => x.ToUpper ()).ToList ();

Or still the same with type inference:

List<string> list = ...;
var uppercase = list.Select (x => x.ToUpper ()).ToList ();

or if you don't mind getting the result as an IEnumerable<string> (an enumerable collection of strings), you could drop the ToList:

List<string> list = ...;
var uppercase = list.Select (x => x.ToUpper ());

Or maybe another one with the C# SQL-like from and select keywords, which is fully equivalent:

List<string> list = ...;
var uppercase = from name in list
                select name => name.ToUpper ();

LINQ is very expressive and very often, I feel that the code is more readable than a plain loop.

Your second question, searching for an item in a list, and wish to exit when that item is found can also be very conveniently be implemented using LINQ. Here is an example of a foreach loop:

List<string> list = ...;
string result = null;
foreach (name in list)
{
    if (name.Contains ("Pierre"))
    {
        result = name;
        break;
    }
}

Here is the straightforward LINQ equivalent:

List<string> list = ...;
string result = list.Where (x => x.Contains ("Pierre")).FirstOrDefault ();

or with the query syntax:

List<string> list = ...;

var results = from name in list
              where name.Contains ("Pierre")
              select name;
string result = results.FirstOrDefault ();

The results enumeration is only executed on demand, which means that effectively, the list will only be iterated until the condition is met, when invoking the FirstOrDefault method on it.

I hope this brings some more context to the for or foreach debate, at least in the .NET world.

Pierre Arnaud
  • 9,402
  • 8
  • 70
  • 102
6

As Stuart Golodetz answered, it's an abstraction.

If you're only using i as an index, as opposed to using the value of i for some other purpose like

   String[] lines = getLines();
   for( int i = 0 ; i < 10 ; ++i ) {
      System.out.println( "line " + i + lines[i] ) ;
   }

then there's no need to know the current value of i, and being able to just leads to the possibility of errors:

   Line[] pages = getPages();
   for( int i = 0 ; i < 10 ; ++i ) {
        for( int j = 0 ; j < 10 ; ++i ) 
             System.out.println( "page " + i + "line " + j + page[i].getLines()[j];
   }

As Andrew Koenig says, "Abstraction is selective ignorance"; if you don't need to know the details of how you iterate some collection, then find a way to ignore those details, and you'll write more robust code.

tpdi
  • 32,745
  • 10
  • 74
  • 117
4

Reasons to use foreach:

  • It prevents errors from creeping in (e.g. you forgot to i++ in the for loop) that could cause the loop to malfunction. There are lots of ways to screw up for loops, but not many ways to screw up foreach loops.
  • It looks much cleaner / less cryptic.
  • A for loop may not even be possible in some cases (for example, if you have an IEnumerable<T>, which cannot be indexed like an IList<T> can).

Reasons to use for:

  • These kinds of loops have a slight performance advantage when iterating over flat lists (arrays) because there is no extra level of indirection created by using an enumerator. (However, this performance gain is minimal.)
  • The object you want to enumerate does not implement IEnumerable<T> -- foreach only operates on enumerables.
  • Other specialized situations; for example, if you are copying from one array to another, foreach will not give you an index variable that you can use to address the destination array slot. for is about the only thing that makes sense in such cases.

The two cases you list in your question are effectively identical when using either loop -- in the first, you just iterate all the way to the end of the list, and in the second you break; once you have found the item you are looking for.

Just to explain foreach further, this loop:

IEnumerable<Something> bar = ...;

foreach (var foo in bar) {
    // do stuff
}

is syntactic sugar for:

IEnumerable<Something> bar = ...;

IEnumerator<Something> e = bar.GetEnumerator();
try {
    Something foo;
    while (e.MoveNext()) {
        foo = e.Current;
        // do stuff
    }
} finally {
    ((IDisposable)e).Dispose();
}
cdhowie
  • 133,716
  • 21
  • 261
  • 264
  • A couple of nitpicks: *(1)* The C# compiler optimises a `foreach` over an array into a `for` so there is *no performance difference whatsoever* between the two options. *(2)* `foreach` doesn't strictly require an `IEnumerable`/`IEnumerator` implementation; so long as the object has an appropriate `GetEnumerator` method (ie, one that returns an object with appropriate `Current` and `MoveNext` members) then you can `foreach` over it. – LukeH Dec 08 '10 at 01:34
  • ...and also, e.Dispose() is only called if e actually implements the IDisposable interface – Isak Savo Dec 08 '10 at 12:16
  • Points taken; however, this pattern is pretty much always used with `IEnumerable` and `IEnumerable` in practice. And these interfaces inherit `IDisposable`. – cdhowie Dec 08 '10 at 15:36
3

If you are iterating over a collection that implements IEnumerable, it is more natural to use foreach because the next member in the iteration is assigned at the same time that the test for reaching the end is done. E.g.,

 foreach (string day in week) {/* Do something with the day ... */}

is more straightforward than

for (int i = 0; i < week.Length; i++) { day = week[i]; /* Use day ... */ }

You can also use a for loop in your class's own implementation of IEnumerable. Simply have your GetEnumerator() implementation use the C# yield keyword in the body of your loop:

yield return my_array[i];
Buggieboy
  • 4,338
  • 4
  • 48
  • 77
2

Java has both of the loop types you have pointed to. You can use either of the for loop variants depending on your need. Your need can be like this

  1. You want to rerun the index of your search item in the list.
  2. You want to get the item itself.

In the first case you should use the classic (c style) for loop. but in the second case you should use the foreach loop.

The foreach loop can be used in the first case also. but in that case you need to maintain your own index.

Lance Roberts
  • 21,279
  • 29
  • 106
  • 128
Vijay Shanker Dubey
  • 4,004
  • 6
  • 27
  • 47
1

If you can do what you need with foreach then use it; if not -- for example, if you need the index variable itself for some reason -- then use for. Simple!

(And your two scenarios are equally possible with either for or foreach.)

LukeH
  • 242,140
  • 52
  • 350
  • 400
1

I could think of several reasons

  1. you can't mess up indexes, also in mobile environment you do not have compiler optimizations and lousily written for loop could do several bounderay checks, where as for each loop does only 1.
  2. you can't change data input size (add / remove elements) while iterating it. Your code does not brake that easily. If you need to filter or transform data, then use other loops.
  3. you can iterate over data structures, that can't be accesses by index, but can be crawled over. For each just needs that you implement iterable interface (java) or extend IEnumerable (c#).
  4. you can have smaller boiler plate, for example when parsing XML it's difference between SAX and StAX, first needs in-memory copy of the DOM to refer to an element latter just iterates over data (it is not as fast, but it is memory efficient)

Note that if you are searching for an item in the list with for each, you most likely are doing it wrongly. Consider using hashmap or bimap to skip the searching all together.

Assuming that programmer want's to use for loop as for each using iterators, there exists a common bug of skipping elements. So in that scene it is more safer.

for ( Iterator<T> elements = input.iterator(); elements.hasNext(); ) {
   // Inside here, nothing stops programmer from calling `element.next();` 
   // more then once.
} 
Margus
  • 18,332
  • 12
  • 51
  • 101
  • Not correct on (4): SAX is an event based API which is quite capable, and usually is so implemented, of generated events from a stream as it is read - it does *not* require a DOM tree in memory. – Lawrence Dol Dec 08 '10 at 05:02
1

one reason not to use foreach at least in java is that it will create an iterator object which will eventually be garbage collected. Thus if you are trying to write code that avoids garbage collection it is better to avoid foreach. However, I believe it is ok for pure arrays because it doesn't create an iterator.

0

It looks like most items are covered... the following are some extra notes that I do not see mentioned regarding your specific questions. These are hard rules as opposed to style preferences one way or the other:

I wish to perform an operation on each item in a list

In a foreach loop, you can not change the value of the iteration variable, so if you are looking to change the value of a specific item in your list you have to use for.

It is also worth noting that the "cool" way is now to use LINQ; there are plenty of resources you can search for if you are interested.

John Rasch
  • 57,880
  • 19
  • 101
  • 136
  • you are correct that in .NET the new hotness is LINQ. I've had this question in mind for a long time and haven't asked until now. – MedicineMan Dec 08 '10 at 01:50
  • I didn't realize you had the `java` tag as well, I probably should point out that this answer is specific to .NET :) – John Rasch Dec 08 '10 at 01:51
  • In a `foreach` loop you cannot assign an element to the container to replace the current element. (Using the term "iteration variable" clouds the issue, because the "iteration variable" has a fundamentally different purpose in the two styles.) However, you absolutely can modify the element, assuming it is mutable. Assuming reference semantics (classes in C#; everything but primitives in a plain array in Java, and maybe not even those - I'd have to test), the changes will be reflected in the container, because you are working with the actual container element, not a copy. – Karl Knechtel Dec 08 '10 at 02:01
  • 4
    Regarding searching, that's absolutely not true, and most of why I -1'd: you can still `break` from a `foreach` style loop. – Karl Knechtel Dec 08 '10 at 02:02
  • @Karl - The key word I used is **efficient**. Please tell me how you can perform a binary search with a `foreach`. – John Rasch Dec 08 '10 at 02:09
  • 2
    Nobody said anything about the container being sorted; implicitly-sorted containers generally provide their own lookup functions anyway; and binary search using a for loop is not iteration. – Karl Knechtel Dec 08 '10 at 02:21
  • @Karl - I'm not sure what point you're trying to make. I should first clarify that this answer is specific to C#. I used the term *iteration variable* very carefully because it is explicitly defined in the C# specification. As for "nobody saying anything about the container being sorted", it is also true that nobody said that the list is *not* sorted. I merely pointed out that, assuming a sorted list (which it obviously it would be in the case of a binary search), you absolutely can not use `foreach` to implement an efficient search algorithm. – John Rasch Dec 08 '10 at 02:34
  • 1
    When one talks at length about looping over collections, and then says "I am searching for an item in a list, and wish to exit when that item is found.", it is clear that one is thinking exclusively about a linear search. The question was about iteration, so a discussion of binary search is simply irrelevant, even though it involves "looping". Further, you attempted to make the point about efficiency while neglecting to mention a crucial precondition (sortedness). – Karl Knechtel Dec 08 '10 at 02:39
  • @Karl - Also, I never said you "can't modify the element". I said you can not *change the value*. The statement "you are working with the actual container element, not a copy" is incorrect. You *are* working with a copy of the reference in the list (assuming the list item is a reference type). – John Rasch Dec 08 '10 at 02:41
  • You are working with the element, via the reference. The point is that the element is not copied. You are only "not working with the actual container element" in a sense in which you are **never** actually "working with an object" in a language with reference semantics. While it's true that you can't "change the iteration variable" in this sense, this doesn't prevent "changing the value of a specific item in the list", unless your definition of "changing a value" somehow does not include mutating an object so as to represent a different value. – Karl Knechtel Dec 08 '10 at 02:42
  • @Karl - At least in C#, the element in a list of reference types *is* a reference. When I say "change the value of a specific item in the list", I'm talking about the reference because *that's what the item is*. Of course you can change (i.e. mutate) the object to which the reference is referring to. As for "my definitions", they are irrelevant; I am using the definitions provided in the C# specification. – John Rasch Dec 08 '10 at 03:02
  • It works the same way in Java; but the phrasing in the initial answer is misleading and justifying it is just playing semantic games. While it is important to understand how reference semantics work, it is also important to not have to worry about them every time you trace through the logic. Describing modifications to a container in terms of "mutating an object" or "replacing an object" is much clearer. – Karl Knechtel Dec 08 '10 at 03:05
  • @Karl - There is nothing to justify. If using precisely specified terminology is "playing semantic games" and using more generalized terminology is "much clearer", feel free to find something else that is not actually written in this answer to declare incorrect. – John Rasch Dec 08 '10 at 03:22
  • 1
    You're implying that breaking out of a loop early is an efficiency of search algorithms because of the juxtaposition of your statement with the one you quoted. This implies that foreach cannot be exited early. You could clarify by stating explicitly what you mean by "efficient algorithm", ie Binary Search, rather than just the ability to exit the loop once the item is found. – Cameron MacFarland Dec 08 '10 at 08:26
  • @Cameron - maybe I just needed some sleep but I see it now... I meant to say "you need to have access to an index if you plan on using an efficient search algorithm" which means you can't use either construct, so I'll remove that portion from the answer since it is not relevant to the question. – John Rasch Dec 08 '10 at 15:12
  • @John - I have a simple rule... never answer questions on SO when I'm tired or about to go to bed. It keeps me out of trouble. :D – Cameron MacFarland Dec 09 '10 at 01:46
0

Talking about clean code, a foreach statement is much quicker to read than a for statement!

Linq (in C#) can do much the same, but novice developers tend to have a hard time reading them!

0

foreach is order of magnitude slower for implementation heavy collection.

I have proof. These are my findings

I used the following simple profiler to test their performance

static void Main(string[] args)
{
    DateTime start = DateTime.Now;
    List<string> names = new List<string>();
    Enumerable.Range(1, 1000).ToList().ForEach(c => names.Add("Name  = " + c.ToString()));
    for (int i = 0; i < 100; i++)
    {
        //For the for loop. Uncomment the other when you want to profile foreach loop
        //and comment this one
        //for (int j = 0; j < names.Count; j++)
          //  Console.WriteLine(names[j]);
        //for the foreach loop
        foreach (string n in names)
        {
            Console.WriteLine(n);
        }
    }
    DateTime end = DateTime.Now;
    Console.WriteLine("Time taken = " + end.Subtract(start).TotalMilliseconds + " milli seconds");

And I got the following results

Time taken = 11320.73 milli seconds (for loop)

Time taken = 11742.3296 milli seconds (foreach loop)

Dan McClain
  • 11,310
  • 9
  • 44
  • 67
sam
  • 27
  • 2
  • While there is nothing wrong with the way you did the time measurement, you should consider using the Stopwatch object which is designed for this task. – Martin Jan 20 '11 at 08:59
  • I would love to see a followup using a stopwatch – MedicineMan Jan 20 '11 at 19:44
  • you should also average the results over several repetitions – MedicineMan Jan 20 '11 at 19:45
  • 3
    I fail to see how 11742 milliseconds is "an order of magnitude slower" than 11321 milliseconds. Looks to me more like 3.7% slower. – Karl Knechtel Aug 23 '11 at 01:07
  • @Karl 3.7% can be quite enough for some projects. Of course, the test presented is far from complete and covers only one specific case, but, still, it is something useful to take in account, IMO. – ThunderGr Nov 09 '12 at 09:42
  • 1
    The point is 3.7% != order of magnitude (I do not think it means what you think it means - http://goo.gl/3JNvF) Maybe he missed a decimal point – Yehosef May 14 '14 at 12:12
  • Enumerable.Range is run from 1 to 1000, while your for loop is run from 0 to 99... – Szörényi Ádám Jul 01 '16 at 10:49
-1

A foreach also notifies you if the collection you're enumerating through changes (i.e. you HAD 7 items in your collection...until another operation on a separate thread removed one and now you only have 6 @_@)

bitxwise
  • 3,414
  • 2
  • 15
  • 21
  • Be cautious, the .NET iterators will throw an exception when getting the next element if you happen to modify a collection you are looping over. Is this what you mean by *protecting* the collection? – Pierre Arnaud Dec 08 '10 at 05:12
  • Yes, that is what I meant. Guess I should change that to "notify", "protect" is a bit of a misnomer hehe – bitxwise Dec 08 '10 at 06:09
  • @Software Monkey - Updated, your highness. – bitxwise Dec 09 '10 at 01:50
-2

Just wanted to add that whoever thinks that foreach gets translated into for and therefore has no performance difference is dead wrong. There are many things that happen under the hood, i.e. the enumeration of the object type which is NOT in a simple for loop. It looks more like an iterator loop:

Iterator iter = o.getIterator();
while (iter.hasNext()){
     obj value = iter.next();
     ...do something
}

which is significantly different than a simple for loop. If you dont understand why, then lookup vtables. Furthermore, who knows whats in the hasNext function? For all we know it could be:

while (!haveiwastedtheprogramstimeenough){
}
now advance

Exageration aside, there are function of unknown implementation and efficiency being called. Since compilers dont optimize accross function boundaries, there is NO optimization happening here, just your simple vtable lookup and function call. This is not just theory, in practice, i have seen significant speedups by switching from foreach to for on the standard C# ArrayList. To be fair, it was an arraylist with about 30,000 items, but still.

chacham15
  • 12,538
  • 21
  • 88
  • 185
  • What language is your example written in? It does not look like valid C# or Java. – finnw Dec 08 '10 at 12:49
  • In any sane collection, there will not be any performance difference. For linked lists, foreach will be faster. – SLaks Dec 08 '10 at 14:24
  • Thats java for those of you who dont know...or are nit-picking. Is an array or arraylist a "sane" collection? The reason that arrays go faster without the iterator is because you can directly index the item meaning that all of the iteration code is wasteful. It may seems small, but imagine when you repeat 1 million times. Or imagine as someone earlier pointed out that the iterator returns a clone of the object. Reeeeealy big slowdowns can occur. Lastly, beacuse linked lists arent directly indexed, the cost of the iteration code is relative small, but still nonzero! – chacham15 Dec 12 '10 at 12:18
  • 2
    This is not nit-picking at all. The Microsoft C# compiler uses pattern-based optimizations when it sees "foreach" statements and one of those optimizations is to transform "foreach" statements over arrays into for(...) statements. It even removes bounds checking in certain cases for additional performance. The pattern-based optimizations were critical in the pre-generic versions of the CLR to try mitigate boxing and unboxing value types in standard collections. – Chuu Feb 29 '12 at 23:01