0

I am trying to convert this code to linq:

foreach (var printer in printers)
{
    if (printer.Installed)
        installedPrinters.Add(printer);
}

I am new to Linq and would appreciate pointers on how it works when iterating through a collection.

Mike
  • 11
  • 2

5 Answers5

3
printers.Where(printer => printer.Installed)
  .ToList()
  .ForEach(printer => installedPrinters.Add(printer));

Note the need to call ToList() before ForEach (see Lambda Expression using Foreach Clause).

Also note that while this works, your original code is probably easier to read... LINQ is cool but don't feel obligated to use it for everything :)

Community
  • 1
  • 1
Robert Levy
  • 28,747
  • 6
  • 62
  • 94
  • I'd also mention that one of the principal developers of c# compiler team (Eric Lippert) [doesn't particularly like the LINQ `.ForEach()`](http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx) (nor do I). The first reason is that doing so violates the functional programming principles that all the other sequence operators are based upon. Clearly the sole purpose of a call to this method is to cause side effects. The purpose of an expression is to compute a value, not to cause a side effect. The purpose of a statement is to cause a side effect. – Erik Philips Jul 12 '14 at 02:20
  • More simply, `printer => installedPrinters.Add(printer)` could be `installedPrinters.Add`. – Ripple Jul 12 '14 at 02:25
  • @Ripple and how do you suppose your alternative would know which printer in the foreach to install? – Erik Philips Jul 12 '14 at 03:07
  • 1
    @ErikPhilips `ForEach` has a signiature of `Action` which `void Add(Printer printer)` fulfills. It just passes the argument in the same way the lambada does. (I agree with your fist comment too btw, he should not be using `ForEach`) – Scott Chamberlain Jul 12 '14 at 03:12
  • @ErikPhilips Each printer will be passed by `ForEach` as @Scott commented. In addition, I assume `installedPrinters.Add` returns `void`. Sorry for my insufficient words. – Ripple Jul 12 '14 at 03:29
  • @Ripple no problem. It was my attempt at adding some extra metadata to the answer so other readers would understand. – Erik Philips Jul 12 '14 at 03:30
3

If you are just trying to create a new list, you could always just do:

var installedPrinters = printers.Where(p => p.Installed).ToList();

If you are adding to a list that may already have items in it, then you could try:

installedPrinters.AddRange(printers.Where(p => p.Installed));

Assuming your installedPrinters is actually a collection that supports AddRange such as List.

bingles
  • 11,582
  • 10
  • 82
  • 93
1

So first use a Where to filter the Installed==true, then run over them with ForEach:

printers.Where(p => p.Installed).ForEach(p => installedPrinters.Add(p));
DavidG
  • 113,891
  • 12
  • 217
  • 223
0
foreach (var printer in printers.Where (p => p.Installed) { installedPrinters.Add(printer); }
antiduh
  • 11,853
  • 4
  • 43
  • 66
MKS
  • 352
  • 3
  • 8
0

Try this

printer.Where(x => x.Installed).ToList()
      .ForEach(
          p=>
            {
              installedPrinters.Add(p)
            }
);
Dennis R
  • 3,195
  • 1
  • 19
  • 24