Resharper, linq inside foreach loop

Resharper suggests using the top example in the bottom example. However, I am under the impression that a new list of items will be created first, and therefore all _executeFunc functions will be executed before the runstoredprocedure is called.

This is generally not a problem, however there are exceptions, and if my hypothesis is correct, my database will not update even though the functions have been started.

foreach (var result in rows.Select(row => _executeFunc(row)))
   {                   
      RunStoredProcedure(result)
   }

      

or

 foreach(var row in rows)
   {
       var result = _executeFunc(row);
       RunStoredProcedure(result);
   }

      

+3


source to share


5 answers


Operators in this case are semantically the same as Select

(and linq in general) use deferred execution of delegates. It will not run the declared queries until the result is implemented, and depending on how you write that query, it will do so in the correct sequence.

A very simple example:

var list = new List<string>{"hello", "world", "example"};

Func<string, string> func = (s) => {
    Console.WriteLine(s);
    return s.ToUpper();
};

foreach(var item in list.Select(i => func(i)))
{
    Console.WriteLine(item);
}

      



leads to

hello
HELLO
world
WORLD
example
EXAMPLE

      

+4


source


The first example _executeFunc(row)

will NOT be called first for every element in rows

before the loop starts foreach

. LINQ will defer execution. See this answer for details .

The order of events will be:

  • Rate the first item in rows

  • Call executeFunc(row)

    in this item
  • Call RunStoredProcedure(result)

  • Repeat with next item in rows



Now if your code was something like this:

foreach (var result in rows.Select(row => _executeFunc(row)).ToList())
{                   
   RunStoredProcedure(result)
}

      

Then LINQ first needs to run .Select

on every item in rows

, because it .ToList()

invokes enumeration of the collection.

+4


source


In the above example, the usage Select

will project the lines yielding

one at a time.

So,

foreach (var result in rows.Select(row => _executeFunc(row)))

basically the same as

foreach(var row in rows)

So Select does something like this

for each row in source
   result = _executeFunc(row)
   yield result

      

This output skips each line backward one by one (this is a little more complicated, but this explanation is sufficient for now).

If you did this instead

foreach (var result in rows.Select(row => _executeFunc(row)).ToList())

The call ToList()

will immediately return a list of lines, which means that _executeFunc () will indeed be called for every line before you I had the opportunity to call RunStoredProcedure()

.

Thus, what Resharper offers is indeed. To be honest, I'm sure the Jetbrains developers know what they are doing :)

+3


source


Select

uses deferred execution. This means that he will be able to:

  • take an element from rows

  • call _executeFunc

    on it
  • call RunStoredProcedure

    by result_executeFunc

And then it will do the same for the next element until the entire list is processed.

+2


source


Execution will be delayed, meaning they will have the same exec

+1


source







All Articles