Foreach or lambda in lists

Asked

Viewed 16,045 times

10

Which one do I get the best performance to get the value of a given in a list? I do foreach or lambda(when possible, of course)? I can have this:

foreach(var i in lista)
{
  var teste = i.NmCampo;
}

Or this:

var teste = lista.Select(campo => campo.NmCampo).FirstOrDefault(c => c == "MeuNome");

Which way I would go in this case. Of course I passed an example with only one line, but I have cases here of several ifs within the foreach and this I’m trading for lambda.

  • 2

    Note that the variable teste has different values in each case. In the first, the variable teste will take the value NmCampo in each iteration of foreach. In the second case teste is with the value of the first line that returns results (for example, in 100 rows of results, the variable will only be with the value of the first line)

  • @Cesarean Michael, this happens due to Firstordefaul, but I can suppress if I need to get a collection. The example is hypothetical only to illustrate what has the best performance. Of course each situation should be studied carefully.

  • right. I just found it odd two examples that did different things :P Which one has better performance? I’m not sure, but I think licks. But I have no grounds to prove it

  • Take a look at this topic http://stackoverflow.com/questions/1044236/nested-foreach-vs-lambda-linq-query-performancelinq-to-objects I think this will be useful

  • @Cesarmiguel If I have to sweep everything foreach is always faster. Performance depends on the internal algorithm and dataset. If the LINQ expression had only the Select she would certainly be slower.

  • By the Renilson link and now by the bigown, really the performance with Foreach in most cases is better, of course there may be situations where the use of LINQ would be convenient, but the foreach scan seems to perform better.

  • @pnet put a real test to show the difference

Show 2 more comments

2 answers

19


@pnet, LINQ tends to be slower than a conventional loop, for the simple reason that Linux adds an overhead to its code. This overhead is basically the conversion of your LINQ in a traditional loop.

Even if it is a conventional loop, we still have performance difference between the for and the foreach, the for can be up to 2x faster than the foreach.

Finally we can still analyze the element that will be covered, the for can be up to 2x faster when traversing a Array than a List<T>. In the end a for with Array, can be up to 4x or 5x faster than a foreach with List<T>.

But remember that everything is a matter of the price you are willing to pay, a foreach is a much more elegant structure than a for, making explicit the intention to traverse that object. In addition a List adds a number of facilities such as search and manipulation.

Now back to the LINQ, this despite being slower than the for/foreach, it is more readable than the loop.

Then the block below will be faster than its equivalent in LINQ

var teste = default(String);
for (int i = 0; i < lista.Count; i++)
{
    if (lista[i].NmCampo == "MeuNome")
    {
        teste = lista[i].NmCampo;
        break;
    }
}

however the LINQ is much more legible:

var teste = lista.Select(campo => campo.NmCampo).FirstOrDefault(c => c == "MeuNome");

As a rule, I usually trade a little performance for code readability.

17

The only way to know for sure is to test and this can change according to the data set and the algorithm to be run on each item.

First let’s note that the two algorithms shown are not equivalent. One takes one data unconditionally and the other takes it conditionally. When you buy things that do different tasks you can’t choose what you do faster, you have to choose what does what you want it to do in the situation.

So let’s compare the same things, between:

foreach(var i in lista) {
    if (i.NmCampo == "MeuNome") { 
        var teste = i.NmCampo;
        break;
    }
}

var teste = lista.Select(campo => campo.NmCampo).FirstOrDefault(c => c == "MeuNome");

The first is clearly faster because it has less abstraction, less indirect, less real code to run.

The second form may be useful but it is more complicated internally. Whether it should be used as such is a matter of taste. Some people would only choose the first one if the performance really makes a difference, and others would only choose LINQ if it showed something more advantageous.

But the first is too big, has a more complicated logic. It may be that legibility is better to choose the second. But it’s still a matter of taste. I’ve already talked about the subject at another answer.

Another important point to note is that it is easy to forget that the break must be there inside the if to shut it down when you find what you want and behave exactly as in FirstOrDefault and the execution of foreach would be slower in most cases because it would have to scan the entire list and with the LINQ expression. But again, the algorithm would be different. It is important to note that not everyone understands all the behavior of the methods available for use with LINQ and all its implications. Hiding a logic isn’t always a good idea. It can make it difficult to understand who is using it if it does not know what is written there. Explicit codes can be better for those who do not know the existing abstractions.

I did a test to see the difference, there’s no point in talking about performance theories because they can prove false in practice or they can be partially true. At a minimum they do not provide enough information to make a conscious decision:

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference. One of the results:

Resultado do for: MeuNome
17497
Resultado do foreach: MeuNome
16669
Resultado do LINQ: MeuNome
57009
Agora acha no primeiro
Resultado do for: MeuNome
12
Resultado do foreach: MeuNome
3
Resultado do LINQ: MeuNome
6599

We can see that the for and the foreach are almost equivalent and it is not possible to see expressive difference. And contrary to popular belief, the foreach may be faster than the for in some situations (in some tests I’ve run it was faster despite derisory difference). We also note that LINQ is much slower. It is not a trivial difference. If you want performance, if it is necessary, run away from LINQ.

When a LINQ expression will be used it must be compiled and this takes a lot of time, so to find the first element in the list is brutally (on average 1000 times) slower than making a loop with a filter inside. Of course having 7000 ticks is nothing but numerically speaking the difference is huge.

Of course this depends on the situation as I said before and needs to analyze whether it will make real difference.

  • really I had based myself on information I had around 2008~2010, a lot has changed since then. I just redo the Micro-benchmark found at: http://codebetter.com/patricksmacchia/2008/11/19/an-easy-and-efficient-way-to-improve-net-code-performances/, and the difference between the for and foreach today is very small. https://dotnetfiddle.net/wAKnL4

  • That’s why performance comparison is complicated. What is worth one day is not worth the other. But it is similar in this case, it may not be in other cases, performance tests are only valid for the specific case. There are an immense amount of factors that can affect up or down performance and most are not controllable or easily perceived by the programmer. But even with this wrong information, you got acceptance and more votes, I don’t understand these people :)

  • I believe that it is a phenomenon similar to that found in the smartphone market, the leader is not the one who has the best product but the one who presented something first. see Samsung and its Galaxy and Motorola line and the Moto line (G).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.