Foreach or lambda in lists

8

What do I get the best performance to get the value of a data in a list? 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 would I go in that case. Of course I have an example with one line only, but I have cases here of several ifs within foreach and this I am trading for lambda .

    
asked by anonymous 11.03.2015 / 13:09

2 answers

17

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

Even though this is a conventional loop, we still have performance differences between for and foreach , for can be up to 2x faster than foreach .

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

But remember that it's all a matter of the price you're willing to pay, a for is a much more elegant structure than a Array , making explicit the intention to go through that object. In addition to that a List adds a series of facilities, such as search and manipulation.

Now returning to foreach , although it is slower than List<T> / foreach , it is more readable than the loop.

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

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

but LINQ is much more readable:

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

As a rule, I usually change a bit of performance by readability of the code.

    
11.03.2015 / 13:50
13

The only way to know for sure is testing, and this may change according to the data set and algorithm to be executed on each item.

First let's note that the two algorithms shown are not equivalent. One takes one die unconditionally and the other hits it conditionally. When you buy things that do different tasks you can not choose what makes it 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 one is clearly faster because it has less abstraction, less indirection, less real code to execute.

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

But the first one gets too big, has a more complicated logic. It may be that for readability it is better to choose the second. But it's still a matter of taste. I already talked about it in another answer .

Another important point to note is that it is easy for a person to forget that break must be there within if to close it when he finds what he wants and behave exactly like FirstOrDefault and there execution of foreach would be slower in most cases because it would have to scan the entire list and with the expression LINQ. But again, the algorithm would be different. It is important to note that not everyone dominates all behavior of methods available for use with LINQ and all its implications. Not always hiding a logic is a good idea. It can make it difficult to understand who is used if she does not know what is written there. Explicit codes may be better for those who do not know the existing abstractions.

I did a test to see the difference, it is no use talking about performance theories because they may be false in practice or may be partially true. At a minimum they do not provide enough information to make a conscious decision:

Benchmark in dotNetFiddle . 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 for and foreach are almost equivalent and you can not see significant difference. And contrary to popular belief, foreach may be faster than for in some situations (in some tests I've run it was faster despite a laughable difference). We also noticed that LINQ is much slower. It is not a trivial difference. If you want performance even if it is needed, get away from LINQ.

When a LINQ expression is used it must be compiled and this takes a long 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 if it will make a real difference.

    
11.03.2015 / 13:51