When I write code in Visual Studio, ReSharper (God bless it!) often suggests me to change my old-school for loop in the more compact foreach form.

And often, when I accept this change, ReSharper goes a step forward, and suggests me to change it again, in a shiny LINQ form.

So, I wonder: are there some real advantages, in these improvements? In pretty simple code execution, I cannot see any speed boost (obviously), but I can see the code becoming less and less readable... So I wonder: is it worth it?

welcome to programmers. Unfortunately your question is too subjective for this QA site. The only answer you could have here is that it is up to you to decide which form you prefer.
–
SimonDec 4 '12 at 9:15

47

If the answer is "It's subjective and you have to decide for yourself, there's no real difference", that doesn't mean that the question is subjective. The answer might have been that there is a difference because (something subtle). How could have the asker known? That's why he's asking the question.
–
iCanLearnDec 4 '12 at 9:39

1

Just a note - LINQ syntax is actually pretty readable if you're familiar with SQL syntax. There are also two formats for LINQ (the SQL-like lambda expressions, and the chained methods), which might make it easier to learn. It could just be ReSharper's suggestions that make it seem unreadable.
–
ShaunaDec 4 '12 at 16:33

8

@Simon this is not a subjective question. There are marked differences between performance and semantics of all three options.
–
Mike BrownDec 4 '12 at 17:40

3

As a rule of thumb, I typically use foreach unless working with a known length array or similar cases where the number of iterations is relevant. As to LINQ-ifying it, I'll usually see what ReSharper makes of a foreach, and if the resulting LINQ statement is tidy / trivial / readable I use it, and otherwise I revert it back. If it would be a chore to re-write the original non-LINQ logic if requirements changed or if it might be necessary to granularly debug thru the logic the LINQ statement is abstracting away from, I don't LINQ it and leave it in long form.
–
Ed HastingsDec 4 '12 at 17:59

The fact that both keywords start by the same three letters doesn't mean that semantically, they are similar. This confusion is extremely error-prone, especially for beginners. Iterating through a collection and doing something with the elements is done with foreach; for doesn't have to and shouldn't be used for this purpose, unless you really know what you're doing.

Let's see what's wrong with it with an example. At the end, you'll find the full code of a demo application used to gather the results.

In the example, we are loading some data from the database, more precisely the cities from Adventure Works, ordered by name, before encountering "Boston". The following SQL query is used:

select distinct [City] from [Person].[Address] order by [City]

The data is loaded by ListCities() method which returns an IEnumerable<string>. Here's how foreach looks like:

When using foreach, ListCities() is called one time and yields 47 items.

When using for, ListCities() is called 94 times and yields 28153 items overall.

What happened?

IEnumerable is lazy. It means that it will do the work only at the moment when the result is needed. Lazy evaluation is a very useful concept, but has some caveats, including the fact that it's easy to miss the moment(s) where the result will be needed, especially in the cases where the result is used multiple times.

In a case of a foreach, the result is requested only once. In a case of a foras implemented in the incorrectly written code above, the result is requested 94 times, i.e. 47 × 2:

Every time cities.Count() is called (47 times),

Every time cities.ElementAt(i) is called (47 times).

Querying a database 94 times instead of one is terrible, but not the worse thing which may happen. Imagine, for example, what would happen if the select query would be preceded by a query which also inserts a row in the table. Right, we would have for which will call the database 2,147,483,647 times, unless it hopefully crashes before.

Of course, my code is biased. I deliberately used the laziness of IEnumerable and wrote it in a way to repeatedly call ListCities(). One can note that a beginner will never do that, because:

The IEnumerable<T> doesn't have the property Count, but only the method Count(). Calling a method is scary, and one can expect its result to not be cached, and not suitable in a for (; ...; ) block.

The indexing is unavailable for IEnumerable<T> and it's not obvious to find the ElementAt LINQ extension method.

Probably most beginners would just convert the result of ListCities() to something they are familiar with, like a List<T>.

Still, this code is very different from the foreach alternative. Again, it gives the same results, and this time the ListCities() method is called only once, but yields 575 items, while with foreach, it yielded only 47 items.

The difference comes from the fact that ToList() causes all data to be loaded from the database. While foreach requested only the cities before "Boston", the new for requires all cities to be retrieved and stored in memory. With 575 short strings, it probably doesn't make much difference, but what if we were retrieving only few rows from a table containing billions of records?

Both produce the same IL. Both have the same result. Both have the same side effects. Of course, this while can be rewritten in a similar infinite for, but it would be even longer and error-prone. You're free to choose the one you find more readable.

LINQ vs. traditional way

As for LINQ, you may want to learn functional programming (FP) - not C# FP stuff, but real FP language like Haskell. Functional languages have a specific way to express and present the code. In some situations, it is superior to non-functional paradigms.

FP is known being much superior when it comes to manipulating lists (list as a generic term, unrelated to List<T>). Given this fact, the ability to express C# code in a more functional way when it comes to lists is rather a good thing.

If you're not convinced, compare the readability of code written in both functional and non-functional ways in my previous answer on the subject.

Question about the ListCities() example. Why would it run only once ? I have had no problems foreaching over yield returns in the past.
–
DanteDec 4 '12 at 11:07

1

He's not saying you would only get one result from the IEnumerable - he's saying that the SQL query (which is the expensive part of the method) would only execute once - this is a good thing. It would then read and yield all of the results from the query.
–
HappyCatDec 4 '12 at 11:12

7

@Giorgio: While this question understandable, having a language's semantics pander to what a beginner might find confusing would not leave us with a very effective language.
–
Steve EversDec 4 '12 at 16:49

3

LINQ isn't just semantic sugar. It provides delayed execution. And in the case of IQueryables (e.g. Entity Framework) allows for the query to be passed and composed until it's iterated (meaning that adding a where clause to a returned IQueryable will result in the SQL passed to the server upon iteration to include that where clause offloading the filtering onto the server).
–
Mike BrownDec 4 '12 at 17:51

1

Much as I like this answer, I think the examples are somewhat contrived. The summary at the end suggests that foreach is more efficient than for, when in actual fact the disparity is a result of deliberately broken code. The thoroughness of the answer redeems itself, but it's easy to see how a casual observer might come to the wrong conclusions.
–
Robert HarveyDec 6 '12 at 23:39

While there are some great expositions already on the differences between for and foreach. There are some gross misrepresentations of the role of LINQ.

LINQ syntax is not just syntactic sugar giving a functional programming approximation to C#. LINQ provides Functional constructs including all the benefits thereof to C#. Combined with returning IEnumerable instead of IList, LINQ provides deferred execution of the iteration. What people typically do now is construct and return an IList from their functions like so

Performing a foreach over the Fibonacci function will return the sequence of 46. If you want the 30th that's all that will be calculated

var thirtiethFib=Fibonacci().Skip(29).Take(1);

Where we get to have a lot of fun is the support in the language for lambda expressions (combined with the IQueryable and IQueryProvider constructs, this allows for functional composition of queries against a variety of data sets, the IQueryProvider is responsible for interpreting the passed in expressions and creating and executing a query using the source's native constructs). I won't go into the nitty gritty details here, but there is a series of blog posts showing how to create a SQL Query Provider here

In summary, you should prefer returning IEnumerable over IList when the consumers of your function will perform a simple iteration. And use the capabilities of LINQ to defer execution of complex queries until they are needed.

Honestly I'd say that Linq makes the intention objectively more readable while for loops make the mechanism objectively more readable.
–
jk.Dec 4 '12 at 9:51

11

I would run as fast as I can from someone that tells me that the for-for-if version is more readable than the intersect version.
–
KonamimanDec 4 '12 at 12:08

1

@Konamiman - That would depend on what a person looks for when they think of "readability." jk.'s comment illustrates this perfectly. The loop is more readable in the sense that you can easily see how it's getting its end result, while the LINQ is more readable in what the end result should be.
–
ShaunaDec 4 '12 at 16:27

1

That's why the loop goes into the implementation, and then you use Intersect everywhere.
–
R. Martinho FernandesDec 4 '12 at 17:39

5

@Shauna: Imagine the for-loop version inside a method doing several other things; it's a mess. So, naturally, you split it into it's own method. Readability-wise, this is the same as IEnumerable<T>.Intersect, but now you've duplicated framework functionality and introduced more code to maintain. The only excuse is if you need a custom implementation for behavioral reasons, but we're only talking about readability here.
–
ChrisDec 4 '12 at 18:11

The difference between LINQ and foreach really boils down to two different programming styles: imperative and declarative.

Imperative: in this style you tell the computer "do this... now do this... now do this now do this". You feed it a program one step at a time.

Declarative: in this style you tell the computer what you want the result to be and let it figure out how to get there.

A classic example of these two styles is comparing assembly code (or C) with SQL. In assembly you give instructions (literally) one at a time. In SQL you express how to join data together and what result you want from that data.

A nice side-effect of declarative programming is that it tends to be a bit higher level. This allows for the platform to evolve underneath you without you having to change your code. For instance:

var foo = bar.Distinct();

What is happening here? Is Distinct using one core? Two? Fifty? We don't know and we don't care. The .NET devs could rewrite it at any time, as long as it continues to perform the same purpose our code could just magically get faster after a code update.

This is the power of functional programming. And the reason that you'll find that code in languages like Clojure, F# and C# (written with a functional programming mindset) is often 3x-10x smaller than it's imperative counterparts.

Finally I like the declarative style because in C# most of the time this allows me to write code that does not mutate the data. In the above example, Distinct() does not change bar, it returns a new copy of the data. This means that whatever bar is, and where ever it came from, it not suddenly changed.

So like the other posters are saying, learn functional programming. It'll change your life. And if you can, do it in a true functional programming language. I prefer Clojure, but F# and Haskell are also excellent choices.

hmm, I appreciate that for a single project this may be the answer, but for the medium to long term you should train your staff, otherwise you have a race to the bottom of code comprehension which doesn't sound like a good idea.
–
jk.Dec 4 '12 at 10:14

15

Actually, there's a third thing that could happen: the other developers could put forth a small amount of effort and actually learn something new and useful. It's not unheard of.
–
Eric KingDec 4 '12 at 14:50

4

@InvertedLlama if I were at a company where the developers need formal training to understand new language concepts then I'd be thinking about finding a new company.
–
Wyatt BarnettDec 4 '12 at 15:35

9

Perhaps you can get away with that attitude with libraries, but when it comes to core language features, that doesn't cut it. You can pick-and-choose frameworks. But a good .NET programmer needs to understand each and every feature of the language, and of the core platform (System.*). And considering that you can't even use EF properly without using Linq, I have to say...in this day and age, if you are a .NET programmer and you don't know Linq, you are incompetent.
–
Timothy BaldridgeDec 4 '12 at 16:13

6

This has enough downvotes already, so I won't add to that, but an argument supporting ignorant/incompetent coworkers is never a valid one.
–
Steve EversDec 4 '12 at 17:09