ChatGPT解决这个技术问题 Extra ChatGPT

LINQ equivalent of foreach for IEnumerable<T>

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?

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

h
huysentruitw

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);
    }
}

Be careful with ToList(), because ToList() creates a copy of the sequence, which could cause performance and memory issues.
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.
PLINQ uses ForAll not ForEach, which is why you wouldn't use ForEach.
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; }
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 LINQ
J
Jon Skeet

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.


For reference, this question poses the same question, and gets input from "the powers that be": stackoverflow.com/questions/858978/…
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.
@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.
@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.
@Anders - 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<_>.
C
Community

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()));
}

What does the resharper warning say?
@reggaeguitar 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.
S
Soner Gönül

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; });

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.
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 confusing
Ok, but prolly a more readable hack: items.All(i => { i.DoStuff(); return true; }
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.
This is side effect programming and IMHO discouraged.
C
Community

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.


Ah, so Select is Map, and Aggregate is Reduce.
D
Dor Rotman

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.


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#.
This is the best answer: deferred execution + fluent api.
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.
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.
l
l33t

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

https://i.stack.imgur.com/OanUT.png

Weakly typed foreach: Memory usage

https://i.stack.imgur.com/7lyz0.png

ForEach extension: Memory usage

https://i.stack.imgur.com/OUwSP.png

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).


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) }
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.
It's relevant in any case you can think of. Unless your programs are 100% loop free.
I believe the word you were looking for is "weakly".
@GregoryShields I take it you read my answer thoroughly :)
L
Legends

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;
        }
    }
}

This is not really a ForEach when you return the item, it's more like a Tap.
A
Athari

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));

The working link to Interactive Extensions: microsoft.com/download/en/details.aspx?id=27203
W
Wolf5

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.


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...
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.
T
Tormod

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.


N
Nenad

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).


You can drop the whole first line and use GetItems directly in foreach
Of course. It is written like this for clarity. So that it is clear what GetItems() method returns.
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.
S
Sklivvz

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)


M
Mark Seemann

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.


Looks like that package is deprecated now
R
Rm558

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.


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;}
This will result in multiple enumerations
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.
@Rm558 - 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).
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.
S
Scott Nimrod

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);
    }

Z
Zar Shardan

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();

If you have to add that disclaimer, you probably shouldn't post it. Just my opinion.
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?
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.
s
solublefish

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


2
2 revs caddzooks

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.


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.
A
Alex

To stay fluent one can use such a trick:

GetItems()
    .Select(i => new Action(i.DoStuf)))
    .Aggregate((a, b) => a + b)
    .Invoke();

I
Israel Margulies

For VB.NET you should use:

listVariable.ForEach(Sub(i) i.Property = "Value")

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.
a
akjoshi

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;
}

What a waste of memory. This calls ToList to add to a list. Why doesn't this just return addresses.Select(a => MapToDomain(a))?