4

Could anyone point out the differences between C# statements and their alike extension methods? e.g: foreach vs. .ForEach(the extension method).

If there are any difference, what are they? Security wise? Performance wise? Which one is better to use? Which one is safer? etc.

And if there are no differences, then why bother writing them?

I've been thinking and searching a bit about this question if mine and didn't find my answer.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Kia Panahi Rad
  • 1,235
  • 2
  • 11
  • 22
  • 9
    [Eric Lippert's blog: “foreach” vs “ForEach”](http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx) – MarcinJuraszek Jan 08 '14 at 22:37
  • 1
    possible duplicate of [Why is there not a ForEach extension method on the IEnumerable interface?](http://stackoverflow.com/questions/101265/why-is-there-not-a-foreach-extension-method-on-the-ienumerable-interface) – Reed Copsey Jan 08 '14 at 22:38
  • Note that tehre isn't a "ForEach" extension method *in the framework* - the closest is `List.ForEach` (which was removed from the Windows Store API) – Reed Copsey Jan 08 '14 at 22:39
  • Can't really get a better explanation than from the man himself. – crush Jan 08 '14 at 22:39
  • I've seen the question mentioned above. But my question about thing like: loading time, performance, security, "side-effects" (which @Kane mentioned) still remain unanswered. – Kia Panahi Rad Jan 08 '14 at 22:47
  • 2
    "if there are no differences, then why bother writing them?" An excellent question! I wish I had a good answer. – Eric Lippert Jan 08 '14 at 23:20
  • @KiaPanahi, what other information would you like to see? It's somewhat difficult to expand more on "it's pretty much the same, minus some very minor things." If you point me in the right direction, I'll revise my answer. – Oliver Kane Jan 09 '14 at 04:29

3 Answers3

6

It depends on the implementation of the extension method you use. Internally, there's really nothing special about most's version of .ForEach.

There would be minimal/negligable time to load the extension method at app load and compile time. There "May" be minimal overhead to convert the .ForEach syntax into the underlying foreach as it's technically only a wrapper. It could potentially cause security issues, but only because it can create closure sitiuations where your objects may not be collected at the time expected (eg: held in scope longer). Ultimately, there's very, very little difference, and it comes down to taste. Unless of course, you're trying to shave off every millisecond, and in that case, using the native body is the best way to go.

I would like to mention that the .ForEach strikes against the premise of using lambda statements being purely functional, that is, it breaks the "functional" style and introduces the possibility of side-effects. Using a foreach body makes the code more readable, and explicit.

Please see: Why there is no ForEach extension method on IEnumerable?

It's a trade off. The extension method is certainly more concise, and it provides compile time checking. The extension method also can introduce difficulty of readability, difficulty of maintainability, and side-effects.

Taken from here

The second reason is that doing so adds zero new representational power to the language. Doing this lets you rewrite this perfectly clear code:

foreach(Foo foo in foos){ statement involving foo; }

into this code:

foos.ForEach((Foo foo)=>{ statement involving foo; });

which uses almost exactly the same characters in slightly different order. And yet the second version is harder to understand, harder to debug, and introduces closure semantics, thereby potentially changing object lifetimes in subtle ways.

Community
  • 1
  • 1
Oliver Kane
  • 888
  • 1
  • 6
  • 23
  • There is no premise of purity in the lambda syntax. – Lee Jan 08 '14 at 22:43
  • @Lee, purity in the sense of of "Purely functional". I'll make that edit. – Oliver Kane Jan 08 '14 at 22:44
  • I'm saying lambdas are not 'purely functional', they are a short-hand for anonymous methods and hence allow side effects. Linq itself promotes purity, and it is often used with lambdas, but lambdas themselves do not. – Lee Jan 08 '14 at 22:51
  • @Lee, I have to concede as you are correct. However, this is the spirit behind the decision of MS to not include this function in the standard library. All the standard operators are intended to be used in a functional way, though you certainly can break that pattern if you wish. I do wish to include this point, but I don't know how to revise without detracting from the point I was trying to make. Suggestions? – Oliver Kane Jan 08 '14 at 22:57
  • The "closure semantics" is indeed a very important detail! As for the rest, I disagree. `foreach` is always superior (see my answer). – l33t Aug 16 '21 at 16:26
1

The provided answers are inaccurate. There are many pitfalls when using a ForEach extension method. E.g. the following extension method may easily become a performance killer:

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

And then we misuse it:

IEnumerable<T> items = new List<T>();
items.ForEach(UpdateItem);

Looks nice, right? Well, here the ForEach() extension method is called on an IEnumerable<T> which means the compiler is forced to allocate a generic enumerator instead of using an optimized, allocation-free version. Then, the Action argument calls for another quite heavy delegate allocation. Put this loop on a hot path and the Garbage Collector will go nuts, causing significant performance issues.

Please see my other answer, where I explain this in much greater detail.

In terms of security, I have seen developers accidentally including a third-party assembly to use a specific ForEach() extension method. This implied shipping an unwanted dependency from who-knows-where with unknown capabilities.

Summary

  • foreach is safer.
  • foreach is more performant.
  • foreach is better. The compiler knows exactly how to deal with it efficiently.
l33t
  • 18,692
  • 16
  • 103
  • 180
-1

.ForEach is similar to Parallel.ForEach. I've seen the regular .ForEach used to develop/debug parallel versions before. Whats nice about it is that you don't have to change a bunch of code to move between the two.

In general, if I have no intentions to do the Parallel.ForEach, then I prefer the regular foreach for readability.

poy
  • 10,063
  • 9
  • 49
  • 74