HugoC4
HugoC4

Reputation: 51

When do LINQ Lambdas execute in a foreach loop

So, to keep it short, I have this bit of code in which I loop through the results of a string split and add them to a list, if they have not occurred before in the loop. This is the code.

var res = new List<string>();
foreach(string s in input.Split(new[] { ", " }, 
              StringSplitOptions.RemoveEmptyEntries))
{
    if(res.All(p => p != s))
        res.Add(s);
}

But after I wrote this code, Visual Studio said I could convert part of the loop into LINQ. However, I'm a bit skeptical about whether this'll work or not.

Basically, my question is, would the lambda expressions be executed on each separate loop, or just once in the beginning?

var res = new List<string>();
foreach (string s in input.Split(new[] { ", " }, 
              StringSplitOptions.RemoveEmptyEntries)
                          .Where(s => res.All(p => p != s)))
{
    res.Add(s);
}

Upvotes: 1

Views: 313

Answers (3)

Marcus Mangelsdorf
Marcus Mangelsdorf

Reputation: 3070

I built on Dmitry's answer and made output a little more verbose to show you what is really going on. Also note, that as Ufuk noted, there a better ways to achieve a list of distinct values.

Feel free to test this for your own and play around with it a little in this dotnetfiddle.

Here is the example:

List<int> input = new List<int> {1, 1, 2, 2, 3, 4};
var res = new List<int>();
foreach (int s in input.Where(s => 
    { 
        Console.WriteLine("lambda: s=" + s);
        Console.WriteLine("lambda: " + s + " contained in res? " + res.Contains(s));
        return !res.Contains(s);
    }))
{
    res.Add(s);
    Console.WriteLine("loop: " + s + " added to res");
    Console.WriteLine();
}

It produces the following output:

lambda: s=1
lambda: 1 contained in res? False
loop: 1 added to res

lambda: s=1
lambda: 1 contained in res? True
lambda: s=2
lambda: 2 contained in res? False
loop: 2 added to res

lambda: s=2
lambda: 2 contained in res? True
lambda: s=3
lambda: 3 contained in res? False
loop: 3 added to res

lambda: s=4
lambda: 4 contained in res? False
loop: 4 added to res

Upvotes: 1

Dmitrii Dovgopolyi
Dmitrii Dovgopolyi

Reputation: 6301

Here is the example of working lazy evaluation of Linq queries.

List<int> vals = new List<int> {1, 1, 2, 2, 3, 4};
var res = new List<int>();
foreach (int s in vals.Where(s => 
                       { 
                           Console.WriteLine("lambda"); 
                           return s % 2 == 0; 
                       }))
{
    Console.WriteLine("loop");
}

And the output will be

lambda
lambda
lambda
loop
lambda
loop
lambda
lambda
loop

As you can see lambda will be evaluated only when the next element is required by foreach loop

Upvotes: 9

Ufuk Hacıoğulları
Ufuk Hacıoğulları

Reputation: 38468

Basically you are just trying to get the distinct values:

var res = input.Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries)
               .Distinct()
               .ToList();

Upvotes: 7

Related Questions