12

Is there any differences (performance or otherwise) between using a foreach loop or the ForEach LINQ method?

For context, this is part of one of my methods:

foreach (var property in typeof(Person).GetProperties())
{
    Validate(property.Name);
}

I can alternatively use this code to perform the same task:

typeof(Person)
    .GetProperties()
    .ToList()
    .ForEach(property => Validate(property.Name));

When would be using the loop structure be better than using method chaining?

Here's another example where I've used the ForEach method, but could just have easily used a foreach loop and a variable:

// LINQ
PrivateData.Database.Users
           .Cast<User>()
           .Where(user => user.LoginType == LoginType.WindowsUser)
           .Select(user => new { Name = user.Name, Login = user.Login })
           .ToList()
           .ForEach(result => WriteObject(result));

// Loop
var users = PrivateData.Database.Users
               .Cast<User>()
               .Where(user => user.LoginType == LoginType.WindowsUser)
               .Select(user => new { Name = user.Name, Login = user.Login });

foreach(var user in users)
{
    WriteObject(user);
}
gunr2171
  • 16,104
  • 25
  • 61
  • 88
Jake
  • 1,701
  • 3
  • 23
  • 44
  • 2
    Note how you have to call `ToList` before you can use `ForEach` in the LINQ style - iterating over something and performing an action like this isn't really the "LINQy" way of doing things. – James Thorpe Nov 02 '15 at 15:14
  • In my experience the Linq is ~2 times slower. The best you can do is measure it in Release mode – Thomas Ayoub Nov 02 '15 at 15:14
  • 1
    @Thomas LINQ *has* no `ForEach` method. The proper LINQ approach is using a `foreach` loop. – Servy Nov 02 '15 at 15:18
  • ForEach is a method on List, so it will require an extra `.ToList()`, slowing everything down and consuming extra memory. Alternatively, you can implement your own ForEach extension method on IEnumerable, then you wouldn't have to run `.ToList()`. I personally perfer having the extension, but as James pointed out it's a somewhat less LINQy way of doing it. – Kvam Nov 02 '15 at 15:21
  • Maybe you did this just an example, but if you don't need the results after these statements, you could simplify both examples by calling `WriteObject` in the `Select`. – Noel Nov 02 '15 at 15:29
  • 1
    What is the faster way to check how much money you carry? 1: open your wallet and look at the bills. 2: buy a new wallet, photocopy the bills and put them in the new wallet, then look at the copies. In software engineering terms: your use of ToList() just so you could use ForEach incurs O(n) storage cost. .NET and modern machines make storage cheap, it is not for free. – Hans Passant Nov 02 '15 at 15:31
  • 1
    @Noel 1. Presumably the method is `void`, so that wouldn't be valid 2. That would mean that the query would never be iterated, and thus the method never run. – Servy Nov 02 '15 at 15:31
  • @JamesThorpe, so am I better off just querying the elements and then going over them in a foreach loop rather than just trying to do everything in one big statement? – Jake Nov 02 '15 at 15:32
  • @Jake In my opinion, yes. Especially if the collection is being `yield`ed from somewhere / read from a database etc. – James Thorpe Nov 02 '15 at 15:32
  • @Noel, I didn't think you could do that in a select method. That's something I'll have to try. – Jake Nov 02 '15 at 15:35
  • @Jake You can't do it in the `Select`, unless you can guarantee that something is going to iterate over the list at some point, or you're still going to call `.ToList` on it or similar – James Thorpe Nov 02 '15 at 15:35
  • @DoctorJones, went to click the 'mark as duplicate' button, but the question's been closed. The top voted answer in that thread explains it for me. – Jake Nov 02 '15 at 15:48
  • 1
    Eric Lippert has a great blog post regarding this http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx – Ivan Stoev Nov 02 '15 at 15:51
  • 1
    Consider `ToList` on the database, if the result is billions of records you'll blow out the memory before the `foreach` executes. Instead `foreach` on the raw query will load each record one at a time. – Cameron MacFarland Nov 02 '15 at 15:53

3 Answers3

12

I would defer you to Eric Lipperts blog "foreach" vs "ForEach". As the previous principal developer on the C# compiler team, I think his opinion is spot on.

Excerpt: (referring to .ForEach())

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. The call site of this thing would look an awful lot like an expression (though, admittedly, since the method is void-returning, the expression could only be used in a “statement expression” context.) It does not sit well with me to make the one and only sequence operator that is only useful for its side effects.

formicini
  • 298
  • 4
  • 16
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
1

The loop is better style because it is a tool made exactly for what you want to do. It integrates nicer with the language. For example, you can break from a loop. Tools understand loops, they do not understand ForEach.

The loop is easier to understand for humans as well. ForEach is very uncommon.

The loop also is faster because there are less indirect calls, less delegate allocations and the optimizer can see more of what you are doing in one place. It also saves the ToList call. You could save that call by writing a custom extension method on IEnumerable<T> as well.

I think the loop is superior in all cases that I can think of. Maybe there's some corner case where the ForEach method would be better style or more convenient for some reason.

PLINQ also has a ForAll which is required for efficiency reasons because it can be parallelized.

usr
  • 168,620
  • 35
  • 240
  • 369
  • "less delegate allocations" that delegate would be compiled to a method would it not, which means it would be no different from a `foreach` with a normal method call. The only difference being the `.ToList()` which as you say, can be solved by a custom extension method... – Phill Nov 02 '15 at 15:21
  • @Phill The *lambda* would be compiled into a method. That method would then be used when constructing a newly allocated delegate that is passed to the method. – Servy Nov 02 '15 at 15:22
  • I don't really follow because his example can be also written like: `.ForEach(WriteObject)` which should compile to roughly the same IL code I believe. (I may try this out of curiosity soon, if I finish what I'm doing) – Phill Nov 02 '15 at 15:25
  • @Phill That code would indeed need to allocate a delegate, you're completely right. That's why it's a differene between `foreach` and `ForEach`, and has nothing to do with the use of a lambda. – Servy Nov 02 '15 at 15:30
  • Downvoted as it's primarily an opinion answer on personal preference for one over the other. – David Arno Nov 02 '15 at 15:49
  • @DavidArno nothing of what I say is objectively disputable. Point out examples of subjectivity. – usr Nov 02 '15 at 22:46
-4

In most cases it's a matter of personal preference. Talking about performance:

Most of the times, LINQ will be a bit slower because it introduces overhead. Do not use LINQ if you care much about performance. Use LINQ because you want shorter better readable and maintainable code.

Kai
  • 5,850
  • 13
  • 43
  • 63