简体   繁体   中英

Difference between "foreach" and extension method: ForEach

Could anyone point out the differences between C# statements and their alike extension methods? eg: 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.

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.

The provided answers are inaccurate. There are many pitfalls when using a ForEach extension method. Eg 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM