LINQ equivalent of foreach for IEnumerable<T>
Asked Answered
F

22

878

I'd like to do the equivalent of the following in LINQ, but I can't figure out how:

IEnumerable<Item> items = GetItems();
items.ForEach(i => i.DoStuff());

What is the real syntax?

Fledgy answered 14/10, 2008 at 9:56 Comment(4)
There is MoreLINQ which has a ForEach extension.Puff
Here's an alternative idea of how this could be possible: visualstudio.uservoice.com/forums/121579-visual-studio-2015/…Sirdar
Whilst not very sexy, this fits on one line without creating a copy via ToList - foreach (var i in items) i.Dostuff();Draw
Some of these links are dead! What was the article that was up-voted so much!Euphrates
P
1059

There is no ForEach extension for IEnumerable; only for List<T>. So you could do

items.ToList().ForEach(i => i.DoStuff());

Alternatively, write your own ForEach extension method:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach(T item in enumeration)
    {
        action(item);
    }
}
Phantasmal answered 14/10, 2008 at 10:0 Comment(18)
I used to have a method like this in my code, but really ToList().ForEach() solves the problem and I feel that Jon's answer, below, is more correct.Tansey
Be careful with ToList(), because ToList() creates a copy of the sequence, which could cause performance and memory issues.Destrier
There are few reasons why ".Foreach()" will be better. 1. Multi-threading, possible by PLINQ. 2. Exceptions, you may want to collect all exception in the loop and throw it at once; and they are noise codes.Echinoid
I wonder if there is a convenient way to make a ForEach implementation like this that can have deferred execution? Might be handy although I think it is probably worse as far as the concern about side effects.Actinon
PLINQ uses ForAll not ForEach, which is why you wouldn't use ForEach.Translucent
Note - because of the copy that the ToList performs, this does will not work for cases where you want to perform an operation that alters the state of each item in the IEnumerable.Alejandroalejo
@Actinon the extension method that Fredrik wrote as alternatively is deferred. IMHO the "alternative" should be listed as the preferred.Penitent
what would you consider an alternative to the foreach if you needed the items in the list to return a value i.e. it will perform a Func<> and no an Action .?Suellensuelo
The more cleaner and readable approach is to use the extension method opposed to the ToList().ForEach(). Although the latter is a quick fix, the ToList() part does not have any value with regards to the functionality of the code. It is sitting in the middle merely as an adapter, which makes the code looks more confusing at first sight.Wherewithal
The first example is terrible, but the second example I think is definitely useful for readability when used in the right situation. Particularly in cases when you can pass just a method, without using the lambda notation. Ex: sequence.ForEach(doSomething); instead of: foreach (Item item in sequence) doSomething(item); This can make a huge difference if you have a lot of these that can be simplified.Breastplate
You should return an IENumerable<T> in the extension method. Like: public static IEnumerable<T> ForAll<T>(this IEnumerable<T> numeration, Action<T> action) { foreach (T item in enumeration) { action(item); } return enumeration; }Kilauea
Note that in the first case the developer 1) saves almost no typing and 2) unnecessarily allocates memory to store the entire sequence as a list before throwing it away. Think before you LINQSalesroom
I added an example to this post for when a property of a collection needs to be processed by a method.Diaphaneity
@KeesC.Bakker Agreed, this would allow chaining items.ForAll(i => i.Name = "Reset Value").SomethingElse(... as well as mutate and pass into some subsequent method.Foregone
#1 also loops the list twice.Euphemie
be wary of NOT introducing a variable ;-)Plainsong
Why should we return IENumerable<T> @KeesC.Bakker?Groove
what does the action parameter do?Gapes
P
428

Fredrik has provided the fix, but it may be worth considering why this isn't in the framework to start with. I believe the idea is that the LINQ query operators should be side-effect-free, fitting in with a reasonably functional way of looking at the world. Clearly ForEach is exactly the opposite - a purely side-effect-based construct.

That's not to say this is a bad thing to do - just thinking about the philosophical reasons behind the decision.

Procryptic answered 14/10, 2008 at 10:10 Comment(21)
For reference, this question poses the same question, and gets input from "the powers that be": stackoverflow.com/questions/858978/…Burks
However, there's one very useful thing that LINQ functions typically provide that foreach () doesn't - the anonymous function taken by Linq functions can also take an index as a parameter, whereas with foreach you must rebuild the classic for (int i..) construct. And functional languages have to allow iteration that has side effects - otherwise you could never do one iota of work with them :) I'd like to point out that the typical functional method would be to return the original enumerable unchanged.Duodenum
@Walt: If a typical functional method returned the original enumerable and didn't have side-effects (which typical functional methods don't) then it would have no effect at all. Perhaps you could clarify your comment?Procryptic
@Jon Skeet: Essentially, with any language, you're always going to have to output or otherwise pass along some material to "get work done" (output to file, progress inform, whatever). That's where foreach constructs have a place in a functional environment - performing those sorts of actions. So saying that it doesn't have side effects is the same as saying you don't need a foreach.Duodenum
@Jon Skeet - As for clarifying my post a bit, perhaps I should rephrase the last sentence: "I'd like to point out that the typical functional approach with a foreach would be to return the original enumerable unchanged"Duodenum
@Walt: I'm still not sure I agree, partly because a typical truly functional approach wouldn't use foreach like this... it would use a functional approach more like LINQ, creating a new sequence.Procryptic
@Jon: Well, that I agree with; hence the "saying it doesn't have side effects is the same as saying you don't need a foreach". But LINQ isn't academically functional, is it? I'd consider it a practical functional construct within C#. Practicality (unfortunately?) requires side effects... And so I don't believe it would be philosophically inappropriate to add this construct to LINQ just because of side effects. It might be more appropriate, however, to provide a method for fetching the index in the body of a foreach. But it would be nice to have in both places.Duodenum
@Walt: Practicality doesn't need side effects everywhere though. Usually I'd use LINQ for the side-effect-free part, and then a foreach loop for the side-effecting part of the code. If you want the index in foreach, you can either use foreach (var pair in sequence.Select((value, index) => new { value, index })) or use my SmartEnumerable class from MiscUtil which is much the same: yoda.arachsys.com/csharp/miscutil/usage/smartenumerable.htmlProcryptic
@Jon: Adding a ForEach to LINQ doesn't encourage using it everywhere. You are right that they don't need to be everywhere though. And I know there's equivalent user code; personally I'd prefer just using an for() loop than constructing a new list of completely new objects just to access the index. Language / official library support would be nice. But yes, user code is a currently viable option.Duodenum
@Stephen Swensen: yes, F# has Seq.iter, but F# also has immutable data structures. when using Seq.iter on these, the original Seq isn't modified; a new Seq with the side-effected elements is returned.Holding
@Holding - Seq.iter doesn't return anything, let alone a new seq with side-effected elements. It really is just about side-effects. You may be thinking of Seq.map, because Seq.iter is precisely equivalent to a ForEach extension method on IEnumerabe<_>.Skimp
@Jon: I do believe your answer is helpful however you failed to mention when you need to close over the loop variable. One might consider "ForEach" instead of "foreach" here. See my answer stackoverflow.com/questions/200574/…. I found myself in this situation today when using moq in a unit test. I actually came here to understand why "ForEach" wasn't provided for IEnumerable before implementing it myself.Unseen
@drstevens: I think I'd probably still use foreach even then, to be honest.Procryptic
I read the Eric Lippert article, and read through the comments on this Q&A, but still don't understand why it's okay for IList.ForEach to cause side-effects while IEnumerable.ForEach should not be allowed to cause side-effects. I agree with all the other arguments against a ForEach, but ForEach would allow for a fluent API. Can someone explain why side-effects are bad for IEnumerable but not for IList?Snell
@Snell Not precisely an answer, but note the UPDATE at the bottom of Lippert's blog...Metro apparently removed List.ForEach: "While the method seems simple it has a number of potential problems when the list gets mutated by the method passed to ForEach. Instead it is recommended that you simply use a foreach loop." -Wes Haggard, BCL Team. That's kind of a practical example of the philosophy "against" side effects Skeet explains.Barbaraanne
Working link to Eric Lipperts article from @AlexAngas's comment: web.archive.org/web/20190118075220/https://…Uncouth
That's not to say this is a bad thing to do. 12 years later, I would strongly disagree. A ForEach extension on IEnumerable<T> is disastrous (see my answer), and the community deserves to know.Spay
@l33t: I think "disastrous" is a massive overstatement, and you may well find that the performance difference becomes insignificant when you actually do something in the loop. I don't particularly care how much time it takes to do nothing.Procryptic
@JonSkeet You're both right and wrong :) It depends on the context, obviously. If some Unity developer comes here and decides to copy a nice-to-have extension method, there will be unhappy faces when their game suddenly stutters due to GC.Spay
@l33t: So yes, just as with every piece of code you ever find on the internet you need to check whether it's appropriate to use in your context. I have no issue with you raising the performance differences between the two approaches, but there's no need for hyperbole. Note that doing anything with LINQ will have the same performance characteristic - are you going to denounce LINQ as "disastrous" as well?Procryptic
@JonSkeet Yes, in fact :D. It's a complex subject though. I'll blog about it some day, and get back to you.Spay
U
41

Update 7/17/2012: Apparently as of C# 5.0, the behavior of foreach described below has been changed and "the use of a foreach iteration variable in a nested lambda expression no longer produces unexpected results." This answer does not apply to C# ≥ 5.0.

@John Skeet and everyone who prefers the foreach keyword.

The problem with "foreach" in C# prior to 5.0, is that it is inconsistent with how the equivalent "for comprehension" works in other languages, and with how I would expect it to work (personal opinion stated here only because others have mentioned their opinion regarding readability). See all of the questions concerning "Access to modified closure" as well as "Closing over the loop variable considered harmful". This is only "harmful" because of the way "foreach" is implemented in C#.

Take the following examples using the functionally equivalent extension method to that in @Fredrik Kalseth's answer.

public static class Enumerables
{
    public static void ForEach<T>(this IEnumerable<T> @this, Action<T> action)
    {
        foreach (T item in @this)
        {
            action(item);
        }
    }
}

Apologies for the overly contrived example. I'm only using Observable because it's not entirely far fetched to do something like this. Obviously there are better ways to create this observable, I am only attempting to demonstrate a point. Typically the code subscribed to the observable is executed asynchronously and potentially in another thread. If using "foreach", this could produce very strange and potentially non-deterministic results.

The following test using "ForEach" extension method passes:

[Test]
public void ForEachExtensionWin()
{
    //Yes, I know there is an Observable.Range.
    var values = Enumerable.Range(0, 10);

    var observable = Observable.Create<Func<int>>(source =>
                            {
                                values.ForEach(value => 
                                    source.OnNext(() => value));

                                source.OnCompleted();
                                return () => { };
                            });

    //Simulate subscribing and evaluating Funcs
    var evaluatedObservable = observable.ToEnumerable().Select(func => func()).ToList();

    //Win
    Assert.That(evaluatedObservable, 
        Is.EquivalentTo(values.ToList()));
}

The following fails with the error:

Expected: equivalent to < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 > But was: < 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 >

[Test]
public void ForEachKeywordFail()
{
    //Yes, I know there is an Observable.Range.
    var values = Enumerable.Range(0, 10);

    var observable = Observable.Create<Func<int>>(source =>
                            {
                                foreach (var value in values)
                                {
                                    //If you have resharper, notice the warning
                                    source.OnNext(() => value);
                                }
                                source.OnCompleted();
                                return () => { };
                            });

    //Simulate subscribing and evaluating Funcs
    var evaluatedObservable = observable.ToEnumerable().Select(func => func()).ToList();

    //Fail
    Assert.That(evaluatedObservable, 
        Is.EquivalentTo(values.ToList()));
}
Unseen answered 1/9, 2011 at 19:24 Comment(2)
What does the resharper warning say?Akbar
@Akbar I haven't used C# in 7 or 8 years, since before C# 5.0 was released, which changed the behavior described here. At the time it gave this warning stackoverflow.com/questions/1688465/…. I doubt that it still warns on this though.Unseen
S
38

You could use the FirstOrDefault() extension, which is available for IEnumerable<T>. By returning false from the predicate, it will be run for each element but will not care that it doesn't actually find a match. This will avoid the ToList() overhead.

IEnumerable<Item> items = GetItems();
items.FirstOrDefault(i => { i.DoStuff(); return false; });
Stratosphere answered 5/10, 2010 at 14:16 Comment(10)
I agree too. It might be a clever little hack, but at first sight, this code isn't clear what it is doing, certainly in comparison to a standard foreach loop.Schoolboy
I had to downvote because while technically correct, your future self and all your successors will hate you forever because instead of foreach(Item i in GetItems()) { i.DoStuff();} you took more characters and made it extremely confusingSalesroom
Ok, but prolly a more readable hack: items.All(i => { i.DoStuff(); return true; }Chrissychrist
I know this is a fairly old post, but I had to downvote it also. I agree it's a clever trick, but it's not maintainable. At first glance it looks like it's doing something with the first item in the list only. This could easily cause more bugs in the future by coders misunderstanding how it functions and what it's supposed to be doing.Ahithophel
Maybe use this so intention is clear? public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action) { enumeration.FirstOrDefault(item => { action(item); return false; }); }Ellsworth
This is side effect programming and IMHO discouraged.Archimedes
Better create your own extension because this "hack" is too ugly with a little extra CPU cost. To be objective: It's a bad decision.Abdicate
@Ellsworth - I agree an extension method is clearer. But given that, why would one implement it using this confusing FirstOrDefault trick, rather than Fredrik's straightforward foreach implementation?Canning
@Chrissychrist I recently started using this syntax because it can be very useful when you first need to check items for nullity, so you just do items?.All(i => { i.DoStuff(); return true; }Iyeyasu
@Chrissychrist any motivation?Iyeyasu
S
31

So many answers, yet ALL fail to pinpoint one very significant problem with a custom generic ForEach extension: Performance! And more specifically, memory usage and GC.

Consider the sample below. Targeting .NET Framework 4.7.2 or .NET Core 3.1.401, configuration is Release and platform is Any CPU.

public static class Enumerables
{
    public static void ForEach<T>(this IEnumerable<T> @this, Action<T> action)
    {
        foreach (T item in @this)
        {
            action(item);
        }
    }
}

class Program
{
    private static void NoOp(int value) {}

    static void Main(string[] args)
    {
        var list = Enumerable.Range(0, 10).ToList();
        for (int i = 0; i < 1000000; i++)
        {
            // WithLinq(list);
            // WithoutLinqNoGood(list);
            WithoutLinq(list);
        }
    }

    private static void WithoutLinq(List<int> list)
    {
        foreach (var item in list)
        {
            NoOp(item);
        }
    }

    private static void WithLinq(IEnumerable<int> list) => list.ForEach(NoOp);

    private static void WithoutLinqNoGood(IEnumerable<int> enumerable)
    {
        foreach (var item in enumerable)
        {
            NoOp(item);
        }
    }
}

At a first glance, all three variants should perform equally well. However, when the ForEach extension method is called many, many times, you will end up with garbage that implies a costly GC. In fact, having this ForEach extension method on a hot path has been proven to totally kill performance in our loop-intensive application.

Similarly, the weakly typed foreach loop will also produce garbage, but it will still be faster and less memory-intensive than the ForEach extension (which also suffers from a delegate allocation).

Strongly typed foreach: Memory usage

No allocations. No GC

Weakly typed foreach: Memory usage

enter image description here

ForEach extension: Memory usage

Lots of allocations. Heavy GC.

Analysis

For a strongly typed foreach the compiler is able to use any optimized enumerator (e.g. value based) of a class, whereas a generic ForEach extension must fall back to a generic enumerator which will be allocated on each run. Furthermore, the actual delegate will also imply an additional allocation.

You would get similar bad results with the WithoutLinqNoGood method. There, the argument is of type IEnumerable<int> instead of List<int> implying the same type of enumerator allocation.

Below are the relevant differences in IL. A value based enumerator is certainly preferable!

IL_0001:  callvirt   instance class
          [mscorlib]System.Collections.Generic.IEnumerator`1<!0> 
          class [mscorlib]System.Collections.Generic.IEnumerable`1<!!T>::GetEnumerator()

vs

IL_0001:  callvirt   instance valuetype
          [mscorlib]System.Collections.Generic.List`1/Enumerator<!0>
          class [mscorlib]System.Collections.Generic.List`1<int32>::GetEnumerator()

Conclusion

The OP asked how to call ForEach() on an IEnumerable<T>. The original answer clearly shows how it can be done. Sure you can do it, but then again; my answer clearly shows that you shouldn't.

Verified the same behavior when targeting .NET Core 3.1.401 (compiling with Visual Studio 16.7.2).

Spay answered 30/6, 2020 at 17:42 Comment(9)
Very clear analysis, not sure if you give as good an account of recommended course of action. Even if it was a link to an article on best practice would be really helpful. I guess you mean don't use linq for this use foreach(x in y){ f(x) }Lotte
Strange: there is a difference between wether you call getenumerator on a interface declared variable vs interface declared variable which seems to cause garbage. As both would call the same actual implementation. Besides that I think when you are scanning a collection so often your algorithm has a computational complexity that is really bad. So I wander what scenario's this is relevant that cannot be simply improved by writing a proper algorithm.Glassworker
It's relevant in any case you can think of. Unless your programs are 100% loop free.Spay
@SørenBoisen You're free to have an opinion. If you prefer to write inefficient code just because you can, then please do. Our company spent millions of dollars analyzing/refactoring this very exact ForEach extension. Once you fully understand its pitfalls, you will simply not allow this junk in your repository.Spay
I believe the word you were looking for is "weakly".Attending
@GregoryShields I take it you read my answer thoroughly :)Spay
@Spay Indeed I did, and an excellent answer it was. :-)Attending
Doesn't foreach acquire the enumerator by calling GetEnumerator? Even if the List<int> is cast to IEnumerable<int>, the implementation of GetEnumerator called should also be the same. Does this optimization only apply to built-in collections?Heterogenetic
Yes, foreach works that way. However, the type of the variable determines which GetEnumerator() it will call. There can be multiple, and only the value-typed enumerator is guaranteed to be optimized. List<T> has such an enumerator, and your custom classes can have such enumerators too.Spay
H
25

I took Fredrik's method and modified the return type.

This way, the method supports deferred execution like other LINQ methods.

EDIT: If this wasn't clear, any usage of this method must end with ToList() or any other way to force the method to work on the complete enumerable. Otherwise, the action would not be performed!

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach (T item in enumeration)
    {
        action(item);
        yield return item;
    }
}

And here's the test to help see it:

[Test]
public void TestDefferedExecutionOfIEnumerableForEach()
{
    IEnumerable<char> enumerable = new[] {'a', 'b', 'c'};

    var sb = new StringBuilder();

    enumerable
        .ForEach(c => sb.Append("1"))
        .ForEach(c => sb.Append("2"))
        .ToList();

    Assert.That(sb.ToString(), Is.EqualTo("121212"));
}

If you remove the ToList() in the end, you will see the test failing since the StringBuilder contains an empty string. This is because no method forced the ForEach to enumerate.

Houseraising answered 2/6, 2010 at 8:54 Comment(4)
Your alternate implementation of ForEach is interesting, however it does not match the behavior of List.ForEach, the signature of which is public void ForEach(Action<T> action). It also does not match the behavior of the Observable.ForEach extension to IObservable<T>, the signature of which is public static void ForEach<TSource>(this IObservable<TSource> source, Action<TSource> onNext). FWIW, the ForEach equivalent on Scala collections, even those which are lazy, also have return type which is equivalent to void in C#.Unseen
This is the best answer: deferred execution + fluent api.Nonflammable
This works exactly the same as calling Select with ToList. The purpose of ForEach is to not having to call ToList. It should execute immediately.Spanos
What would be the benefit of having this "ForEach", whose execution is deferred, vs. one that executes immediately? Deferring (which is inconvenient in how ForEach will be used) doesn't ameliorate the fact that ForEach only performs useful work if the Action has side-effects [the usual complaint that is made against such a Linq operator]. So, how does this change help? In addition, the added "ToList()" to force it to execute, serves no useful purpose. Its an accident waiting to happen. The point of "ForEach" is its side-effects. If you WANT a returned enumeration, SELECT makes more sense.Canning
P
25

Keep your Side Effects out of my IEnumerable

I'd like to do the equivalent of the following in LINQ, but I can't figure out how:

As others have pointed out here and abroad LINQ and IEnumerable methods are expected to be side-effect free.

Do you really want to "do something" to each item in the IEnumerable? Then foreach is the best choice. People aren't surprised when side-effects happen here.

foreach (var i in items) i.DoStuff();

I bet you don't want a side-effect

However in my experience side-effects are usually not required. More often than not there is a simple LINQ query waiting to be discovered accompanied by a StackOverflow.com answer by either Jon Skeet, Eric Lippert, or Marc Gravell explaining how to do what you want!

Some examples

If you are actually just aggregating (accumulating) some value then you should consider the Aggregate extension method.

items.Aggregate(initial, (acc, x) => ComputeAccumulatedValue(acc, x));

Perhaps you want to create a new IEnumerable from the existing values.

items.Select(x => Transform(x));

Or maybe you want to create a look-up table:

items.ToLookup(x, x => GetTheKey(x))

The list (pun not entirely intended) of possibilities goes on and on.

Paraphrast answered 26/12, 2012 at 22:56 Comment(1)
Ah, so Select is Map, and Aggregate is Reduce.Didst
K
18

If you want to act as the enumeration rolls you should yield each item.

public static class EnumerableExtensions
{
    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
    {
        foreach (var item in enumeration)
        {
            action(item);
            yield return item;
        }
    }
}
Kaz answered 31/7, 2015 at 16:4 Comment(2)
This is not really a ForEach when you return the item, it's more like a Tap.Unworldly
@Unworldly this isn't angularLayette
S
11

There is an experimental release by Microsoft of Interactive Extensions to LINQ (also on NuGet, see RxTeams's profile for more links). The Channel 9 video explains it well.

Its docs are only provided in XML format. I have run this documentation in Sandcastle to allow it to be in a more readable format. Unzip the docs archive and look for index.html.

Among many other goodies, it provides the expected ForEach implementation. It allows you to write code like this:

int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8 };

numbers.ForEach(x => Console.WriteLine(x*x));
Sis answered 15/8, 2011 at 15:49 Comment(1)
The working link to Interactive Extensions: microsoft.com/download/en/details.aspx?id=27203Ensconce
E
8

According to PLINQ (available since .Net 4.0), you can do an

IEnumerable<T>.AsParallel().ForAll() 

to do a parallel foreach loop on an IEnumerable.

Eider answered 24/10, 2015 at 21:24 Comment(2)
as long as your action is threadsafe, all is good. but what will happen if you have a non-threadsafe action to perform? it can cause quite a mayhem...Dollfuss
True. It is not thread safe, different threads will be used from some thread pool... And I need to revise my answer. There is no ForEach() when I try it now.. Must have been my code containing an Extension with ForEach when I pondered with this.Eider
D
7

The purpose of ForEach is to cause side effects. IEnumerable is for lazy enumeration of a set.

This conceptual difference is quite visible when you consider it.

SomeEnumerable.ForEach(item=>DataStore.Synchronize(item));

This wont execute until you do a "count" or a "ToList()" or something on it. It clearly is not what is expressed.

You should use the IEnumerable extensions for setting up chains of iteration, definining content by their respective sources and conditions. Expression Trees are powerful and efficient, but you should learn to appreciate their nature. And not just for programming around them to save a few characters overriding lazy evaluation.

Darrickdarrill answered 31/8, 2010 at 6:43 Comment(0)
L
5

Many people mentioned it, but I had to write it down. Isn't this most clear/most readable?

IEnumerable<Item> items = GetItems();
foreach (var item in items) item.DoStuff();

Short and simple(st).

Luu answered 8/7, 2012 at 22:47 Comment(3)
You can drop the whole first line and use GetItems directly in foreachVandiver
Of course. It is written like this for clarity. So that it is clear what GetItems() method returns.Luu
Now when I read my comment I see it seems like I'm telling you something you don't know. I didn't mean that. What I meant is that foreach (var item in GetItems()) item.DoStuff(); is just a beauty.Vandiver
S
4

Now we have the option of...

        ParallelOptions parallelOptions = new ParallelOptions();
        parallelOptions.MaxDegreeOfParallelism = 4;
#if DEBUG
        parallelOptions.MaxDegreeOfParallelism = 1;
#endif
        Parallel.ForEach(bookIdList, parallelOptions, bookID => UpdateStockCount(bookID));

Of course, this opens up a whole new can of threadworms.

ps (Sorry about the fonts, it's what the system decided)

Saveall answered 2/6, 2011 at 15:16 Comment(0)
A
4

As numerous answers already point out, you can easily add such an extension method yourself. However, if you don't want to do that, although I'm not aware of anything like this in the BCL, there's still an option in the System namespace, if you already have a reference to Reactive Extension (and if you don't, you should have):

using System.Reactive.Linq;

items.ToObservable().Subscribe(i => i.DoStuff());

Although the method names are a bit different, the end result is exactly what you're looking for.

Alrich answered 5/1, 2014 at 20:27 Comment(1)
Looks like that package is deprecated nowAkbar
A
4

ForEach can also be Chained, just put back to the pileline after the action. remain fluent


Employees.ForEach(e=>e.Act_A)
         .ForEach(e=>e.Act_B)
         .ForEach(e=>e.Act_C);

Orders  //just for demo
    .ForEach(o=> o.EmailBuyer() )
    .ForEach(o=> o.ProcessBilling() )
    .ForEach(o=> o.ProcessShipping());


//conditional
Employees
    .ForEach(e=> {  if(e.Salary<1000) e.Raise(0.10);})
    .ForEach(e=> {  if(e.Age   >70  ) e.Retire();});

An Eager version of implementation.

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enu, Action<T> action)
{
    foreach (T item in enu) action(item);
    return enu; // make action Chainable/Fluent
}

Edit: a Lazy version is using yield return, like this.

public static IEnumerable<T> ForEachLazy<T>(this IEnumerable<T> enu, Action<T> action)
{
    foreach (var item in enu)
    {
        action(item);
        yield return item;
    }
}

The Lazy version NEEDs to be materialized, ToList() for example, otherwise, nothing happens. see below great comments from ToolmakerSteve.

IQueryable<Product> query = Products.Where(...);
query.ForEachLazy(t => t.Price = t.Price + 1.00)
    .ToList(); //without this line, below SubmitChanges() does nothing.
SubmitChanges();

I keep both ForEach() and ForEachLazy() in my library.

Advised answered 23/2, 2015 at 21:30 Comment(6)
Have you tested this? There are several context where this method behaves contra intuitively. Better would be foreach(T item in enu) {action(item); yield return item;}Elenor
This will result in multiple enumerationsKaz
Interesting. Pondering when I would want to do the above, for a sequence of 3 actions, rather than foreach (T item in enu) { action1(item); action2(item); action3(item); }? A single, explicit, loop. I guess if it was important to do all the action1's BEFORE starting to do action2's.Canning
@Advised - your approach using "yield return". Pro: only enumerates the original sequence once, so works correctly with a wider range of enumerations. Con: if you forget ".ToArray()" at end, nothing happens. Though the failure will be obvious, not overlooked for long, so not a major cost. Doesn't "feel clean" to me, but is the right tradeoff, if one is going down this road (a ForEach operator).Canning
This code is not safe from transactional point of view. What if it fails in ProcessShipping()? You email buyer, charge his credit card, but never send him his stuff? Certainly asking for problems.Desorb
This is equivalent to a Select. There's no reason to duplicate that functionality, just return the original value from your iteration function.Reaper
D
3

Inspired by Jon Skeet, I have extended his solution with the following:

Extension Method:

public static void Execute<TSource, TKey>(this IEnumerable<TSource> source, Action<TKey> applyBehavior, Func<TSource, TKey> keySelector)
{
    foreach (var item in source)
    {
        var target = keySelector(item);
        applyBehavior(target);
    }
}

Client:

var jobs = new List<Job>() 
    { 
        new Job { Id = "XAML Developer" }, 
        new Job { Id = "Assassin" }, 
        new Job { Id = "Narco Trafficker" }
    };

jobs.Execute(ApplyFilter, j => j.Id);

. . .

public void ApplyFilter(string filterId)
{
    Debug.WriteLine(filterId);
}
Diaphaneity answered 11/9, 2014 at 0:17 Comment(0)
P
2

This "functional approach" abstraction leaks big time. Nothing on the language level prevents side effects. As long as you can make it call your lambda/delegate for every element in the container - you will get the "ForEach" behavior.

Here for example one way of merging srcDictionary into destDictionary (if key already exists - overwrites)

this is a hack, and should not be used in any production code.

var b = srcDictionary.Select(
                             x=>
                                {
                                  destDictionary[x.Key] = x.Value;
                                  return true;
                                }
                             ).Count();
Punctilious answered 3/7, 2012 at 0:47 Comment(3)
If you have to add that disclaimer, you probably shouldn't post it. Just my opinion.Begay
How the hell is this better than foreach(var tuple in srcDictionary) { destDictionary[tuple.Key] = tuple.Value; }? If not in production code where and why should you ever use this?Salesroom
This just to show it is possible in principle. It also happens to do what OP asked for, and I clearly indicated it should not be used in production, still curious and has educational value.Punctilious
F
2

MoreLinq has IEnumerable<T>.ForEach and a ton of other useful extensions. It's probably not worth taking the dependency just for ForEach, but there's a lot of useful stuff in there.

https://www.nuget.org/packages/morelinq/

https://github.com/morelinq/MoreLINQ

Fitzpatrick answered 19/10, 2018 at 7:5 Comment(0)
A
1

I respectually disagree with the notion that link extension methods should be side-effect free (not only because they aren't, any delegate can perform side effects).

Consider the following:

   public class Element {}

   public Enum ProcessType
   {
      This = 0, That = 1, SomethingElse = 2
   }

   public class Class1
   {
      private Dictionary<ProcessType, Action<Element>> actions = 
         new Dictionary<ProcessType,Action<Element>>();

      public Class1()
      {
         actions.Add( ProcessType.This, DoThis );
         actions.Add( ProcessType.That, DoThat );
         actions.Add( ProcessType.SomethingElse, DoSomethingElse );
      }

      // Element actions:

      // This example defines 3 distict actions
      // that can be applied to individual elements,
      // But for the sake of the argument, make
      // no assumption about how many distict
      // actions there may, and that there could
      // possibly be many more.

      public void DoThis( Element element )
      {
         // Do something to element
      }

      public void DoThat( Element element )
      {
         // Do something to element
      }

      public void DoSomethingElse( Element element )
      {
         // Do something to element
      }

      public void Apply( ProcessType processType, IEnumerable<Element> elements )
      {
         Action<Element> action = null;
         if( ! actions.TryGetValue( processType, out action ) )
            throw new ArgumentException("processType");
         foreach( element in elements ) 
            action(element);
      }
   }

What the example shows is really just a kind of late-binding that allows one invoke one of many possible actions having side-effects on a sequence of elements, without having to write a big switch construct to decode the value that defines the action and translate it into its corresponding method.

Avra answered 14/10, 2008 at 9:56 Comment(1)
There's a difference between whether an extension method CAN have side-effectsand whether it SHOULD have. You're only pointing out that it can have, while there may be very good reasons to propose that they should not have side effects. In functional programming, all functions are side-effect free, and when using functional programming constructs you may want to assume that they are.Haemoid
H
1

To stay fluent one can use such a trick:

GetItems()
    .Select(i => new Action(i.DoStuf)))
    .Aggregate((a, b) => a + b)
    .Invoke();
Herlindaherm answered 28/2, 2019 at 17:38 Comment(0)
G
-1

For VB.NET you should use:

listVariable.ForEach(Sub(i) i.Property = "Value")
Gignac answered 14/3, 2013 at 19:41 Comment(1)
NOTE: This compiles only if you have a List or IList. For a general IEnumerable, write the VB equivalent of the accepted answer's ForEach extension method.Canning
B
-3

Yet another ForEach Example

public static IList<AddressEntry> MapToDomain(IList<AddressModel> addresses)
{
    var workingAddresses = new List<AddressEntry>();

    addresses.Select(a => a).ToList().ForEach(a => workingAddresses.Add(AddressModelMapper.MapToDomain(a)));

    return workingAddresses;
}
Barnes answered 17/7, 2010 at 23:16 Comment(1)
What a waste of memory. This calls ToList to add to a list. Why doesn't this just return addresses.Select(a => MapToDomain(a))?Salesroom

© 2022 - 2024 — McMap. All rights reserved.