155

I have recently started off with LINQ and its amazing. I was wondering if LINQ would allow me to apply a function - any function - to all the elements of a collection, without using foreach. Something like python lambda functions.

For example if I have a int list, Can I add a constant to every element using LINQ

If i have a DB table, can i set a field for all records using LINQ.

I am using C#

Midhat
  • 17,454
  • 22
  • 87
  • 114

8 Answers8

163

A common way to approach this is to add your own ForEach generic method on IEnumerable<T>. Here's the one we've got in MoreLINQ:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    source.ThrowIfNull("source");
    action.ThrowIfNull("action");
    foreach (T element in source)
    {
        action(element);
    }
}

(Where ThrowIfNull is an extension method on any reference type, which does the obvious thing.)

It'll be interesting to see if this is part of .NET 4.0. It goes against the functional style of LINQ, but there's no doubt that a lot of people find it useful.

Once you've got that, you can write things like:

people.Where(person => person.Age < 21)
      .ForEach(person => person.EjectFromBar());
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 15
    I never really understood the urge people have to do that. A foreach loop is more readable to my eyes; having a separation between the "functional" part that gets the data and the "action" part that operates on it helps clarify the structure of algorithms. – mqp May 05 '09 at 06:14
  • 16
    Yes, I generally prefer a foreach loop myself. On the other hand, if you've already been presented with a delegate to apply to each element, I'm not sure it's much more readable to call that delegate in an explicit foreach loop. I wouldn't use this often, but just occasionally it seems like a nice solution. – Jon Skeet May 05 '09 at 06:52
  • 2
    @Lodewijk: In what way is using a method which *has* to have side-effects in order to be any use functional? The `Where` part is functional... the `ForEach` part not so much, IMO. – Jon Skeet Mar 26 '14 at 18:32
  • Not in the functional-ishness part. Just in syntax. – Lodewijk Mar 26 '14 at 18:47
  • @Lodewijk: Right, and that's where I question whether you're really getting any benefit. Why have code which *looks* somewhat functional, but violates the normal aims of functional programming? What's the benefit of that over a `foreach` loop? It feels like neither one thing nor the other to me. – Jon Skeet Mar 26 '14 at 18:48
  • 3
    It's definitely terrible to do an in-place change instead of returning the new type. That's going to confuse the hell out of a ton of programmers. The benefit is reduced to not having to nest foreaches or otherwise write ugly code. Oneliners can be very readable. – Lodewijk Mar 26 '14 at 18:56
  • @Lodewijk Were your intentions to mean _declarative_? – Alex Nov 11 '14 at 03:30
  • 1
    @Alex, probably not. What do you mean? These "functional-ish" functions are ways to extend the control-flow, "map" specifically gets a lot of love. It makes it easy to take a collection and apply a function to everything in it. Having "map" instead of a 4 line foreach is good because it shows what it does less ambiguously (think zero-or-one-indexing-headaches), and briefer. Having map return a new collection instead of doing inline-changes is more standard and more versatile. This "ForEach" isn't a map function though, and has less advantage over regular foreach loops. – Lodewijk Nov 12 '14 at 23:29
  • @Lodewijk Well, the fundamental thing about declarative programming is that it is supposed to express _what_ to do, instead of _how_ to do it. It sounded like this was what you where after, being "less ambigious", "breifer" and "not the functional-ishness, just the syntax". Just like linq in general - a more declarative way to express complex logical operations. – Alex Dec 01 '14 at 15:53
  • how is this different to something like the select() linq method? – BenKoshy Mar 20 '17 at 09:20
  • 1
    @BKSpurgeon: `Select` is a projection: 1) it's lazily evaluated; just calling it won't do anything. 2) `Select` produces a result - `ForEach` doesn't. – Jon Skeet Mar 20 '17 at 09:24
  • @mquander I have a practical use case. I need to inject some logging between a pipeline of linq statements – Martin Capodici Nov 10 '17 at 06:11
  • 1
    @Martin: ForEach won't help you there - but a Select delegate that logs then returns it's input, or a Where delegate that logs then returns true would both work... – Jon Skeet Nov 10 '17 at 06:42
  • @JonSkeet thanks. I realized once I tried it didn't work. I found another way entirely for this problem, but next time I will consider the Select(...) way. It feels a bit "naughty" to introduce a side effect in Select, though. But I'll live. – Martin Capodici Nov 13 '17 at 18:27
  • 1
    I know this is an old question. I find the forEach very useful in RxJS, it feels like an omission in Linq currently, and I don't think it will confuse people as the purpose of a forEach lambda is to modify the items or do something specific with them, especially useful when dealing with EF entities where you definitely do not want new types. Our RxJs code is very legible and compact. Thank you @JonSkeet for this answer. We won't use all the time, but there are times where it will save quite a bit of foreach boiler plate. – Max Jan 27 '19 at 18:06
105

The idiomatic way to do this with LINQ is to process the collection and return a new collection mapped in the fashion you want. For example, to add a constant to every element, you'd want something like

var newNumbers = oldNumbers.Select(i => i + 8);

Doing this in a functional way instead of mutating the state of your existing collection frequently helps you separate distinct operations in a way that's both easier to read and easier for the compiler to reason about.

If you're in a situation where you actually want to apply an action to every element of a collection (an action with side effects that are unrelated to the actual contents of the collection) that's not really what LINQ is best suited for, although you could fake it with Select (or write your own IEnumerable extension method, as many people have.) It's probably best to stick with a foreach loop in that case.

mqp
  • 70,359
  • 14
  • 95
  • 123
  • 3
    Not to mention mutating a collection while iterating over it is dangerous, to impossible, depending on the language. – Soviut May 05 '09 at 06:05
  • 16
    In C#, mutating the elements of the collection is fair game, but adding to or removing from the collection may either fail or yield unwanted results. – mqp May 05 '09 at 06:06
  • using the Select method only really helps with certain types, like int. What if you wanted to set the property of the objects in your list to a certain value? wouldn't it be simpler and more scalable to use .ForEach()? – andy May 05 '09 at 06:12
  • If you already knew the new value, then typically (in the spirit of LINQ) you would tend to make a new list with the appropriate values in it, instead of changing the old one. Of course, if you do have a list and you really want to change that particular list -- maybe it's databound to something -- then .ForEach() is fine, too. – mqp May 05 '09 at 06:16
  • LINQ defer execution might be a problem with `Select` if you don't iterate later on the result. – Michel Feinstein Oct 21 '16 at 02:11
  • @Soviut `ForEach` doesn't mutate the collection. It may - and is often used to - edit the elements in the collection. Personally, I return the edited collection as a result, but your mileage may vary. – Suncat2000 Jan 29 '19 at 15:43
  • @andy Select method works for your use case as well (setting property of object to certain value). Example. `myItems.Select(item => { item.myProperty = someValue(); return item; } );` – Default Aug 21 '20 at 05:40
51

You could also consider going parallel, especially if you don't care about the sequence and more about getting something done for each item:

SomeIEnumerable<T>.AsParallel().ForAll( Action<T> / Delegate / Lambda )

For example:

var numbers = new[] { 1, 2, 3, 4, 5 };
numbers.AsParallel().ForAll( Console.WriteLine );

HTH.

Jaans
  • 4,598
  • 4
  • 39
  • 49
  • 1
    Please be careful of AsParallel().ForAll() as it causes unpredictive result. For example I have a button to execute this code when clicked: myEnumerable.AsParallel().ForAll(i as string => otherDictionary.Add(i, 0)) . It will add null as a key to otherDictionary. I had to rewrote to use foreach loop. Weird. – YukiSakura Dec 22 '15 at 08:13
  • 5
    @YukiSakura Not really AsParallel().ForAll()'s fault - The bits that are dangerous is using shared stated between multiple threads and then that the cast of "i as string" is the possible cause passing in a null key. Care to share a more complete sample of your code for feedback on how to improve? – Jaans Dec 24 '15 at 06:09
43

haha, man, I just asked this question a few hours ago (kind of)...try this:

example:

someIntList.ForEach(i=>i+5);

ForEach() is one of the built in .NET methods

This will modify the list, as opposed to returning a new one.

Razvan Dumitru
  • 11,815
  • 5
  • 34
  • 54
andy
  • 8,775
  • 13
  • 77
  • 122
  • 15
    Note that this only works on actual List collections, unless you've defined your own ForEach method to do it. – mqp May 05 '09 at 06:05
  • 4
    I believe mquander was referring to the fact that ForEach is not defined on IEnumerable, just List – Odrade Jul 29 '10 at 16:03
  • 1
    Yes, it won't work in most cases, because usually you will get an IEnumerable from your link query – Torben Junker Kjær Oct 27 '10 at 13:49
  • 12
    I find most of the time adding `.ToList().ForEach(...)` is all I need. – Tod May 01 '13 at 22:27
  • Why this gives me : error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement – abdou93 Feb 28 '22 at 21:10
14

Or you can hack it up.

Items.All(p => { p.IsAwesome = true; return true; });
Razvan Dumitru
  • 11,815
  • 5
  • 34
  • 54
AGCodes
  • 622
  • 1
  • 8
  • 22
  • 14
    This is hacking "All" to turn it into "ForEach". I have a bad feeling that this will mislead some newbie into thinking that "All" means "Execute on all elements". – ToolmakerSteve Jul 13 '16 at 16:04
  • Interesting. Does this actually edit the underlying collection? Are the objects returned copies? – Zimano Jun 14 '19 at 19:05
  • 1
    @Zimano It does edit the underlying collection but does not return copies. – AGCodes Jan 06 '20 at 02:37
6

For collections that do not support ForEach you can use static ForEach method in Parallel class:

var options = new ParallelOptions() { MaxDegreeOfParallelism = 1 };
Parallel.ForEach(_your_collection_, options, x => x._Your_Method_());
zmechanic
  • 1,842
  • 21
  • 27
2

You can try something like

var foo = (from fooItems in context.footable select fooItems.fooID + 1);

Returns a list of id's +1, you can do the same with using a function to whatever you have in the select clause.

Update: As suggested from Jon Skeet this is a better version of the snippet of code I just posted:

var foo = context.footable.Select(foo => foo.fooID + 1);
Drahcir
  • 12,311
  • 19
  • 63
  • 76
  • 1
    I'd suggest that in cases where you just need to do a simple projection, query expressions are over the top. I'd use "var foo = context.footable.Select(foo => foo.fooID + 1);" – Jon Skeet May 05 '09 at 06:13
-1

I found some way to perform in on dictionary contain my custom class methods

foreach (var item in this.Values.Where(p => p.IsActive == false))
            item.Refresh();

Where 'this' derived from : Dictionary<string, MyCustomClass>

class MyCustomClass 
{
   public void Refresh(){}
}