views:

359

answers:

5

From what I can see, the ForEach method is available only for the List class.

Why is that? I can see no reason for ForEach not to be available to any class implementing the IEnumerable/IEnumerator interfaces, and this is a really useful method if you need to perform a small action (1 line is more readable than 1 line + 2 boilerplate foreach syntax...).

Update: I'll clarify my question. There are perfectly valid reasons for including ForEach in sequences. There are perfectly good reasons for not including ForEachin all sequences.

But I cannot understand why would ForEach be included in just some of the sequences.

+7  A: 

You are right, the method is defined in the List class. However, its pretty easy to create a extension method that does the same thing.

public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
    foreach (var t in enumerable)
        action(t);
}
Mattias Jakobsson
Better yet, just write a `foreach` loop and forget about extension methods. I see no sense in duplicating existing C# functionality unless you are trying to expose it to a different .NET language that doesn't support `foreach` semantics.
Aaronaught
@ Aaronaught. I agree with you. I usually go for a simple foreach statement as I think that is just as readable as this. I only gave this example as that was what the author was asking for.
Mattias Jakobsson
There are advantages to using the ForEach method that are not apparent in a small example such as this. In some cases readability might be an advantage, if the action that you need to take is very small.
Dave Van den Eynde
I agree with Dave, it is especially more readable when you need nested foreach's.
BlueRaja - Danny Pflughoeft
+21  A: 

See Eric Lippert's post: "foreach" vs "ForEach"

A number of people have asked me why there is no Microsoft-provided “ForEach” sequence operator extension method. The List class has such a method already of course, but there’s no reason why such a method could not be created as an extension method for all sequences.

...

But we can go a bit deeper here. I am philosophically opposed to providing such a method, for two reasons.

...

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 second reason is that doing so adds zero new representational power to the language.

...

Well, the VS Languages team does not have any influence on what goes into List. I personally find the "ForEach" method on List philosophically troubling for all the same reasons that I would find an extension method on IEnumerable troubling. (And the VSL team does control that.) The one mitigating factor is that List is clearly designed to be a mutable, not-side-effect-free data structure, so using expressions that mutate it seems slightly less bad. -- Eric

Ahmad Mageed
+1 Excellent link
Binary Worrier
+1. For me the key point is the debugging aspect. Btw, in every project I've been involved in since the beginning of System.Linq, someone has implemented the solution-to-the-perceived-problem extension method. And then proceeded to abuse it heavily. The horror... And @Ahmad, thx for the rep! ;-)
Lette
@Lette thanks, and you're welcome :)
Ahmad Mageed
What I don't understand after reading the article is, why did they provide this superfluous method for List?
Elazar Leibovich
@Elazar there's an answer to that in the comments! Read before you ask! The answer is that the team which worked on List<T> is not the team which worked on LINQ, see the updated the answer.
Elazar Leibovich
@Elazar cracked me up replying to yourself!
Ahmad Mageed
So... it's there because of corporate politics?
BlueRaja - Danny Pflughoeft
+2  A: 

Correct. However, if you want to use the advantage of ForEach loop, there's a method called "ToList" as shown below used to convert an array back to List.

String[] array = new String[3];
List<String> list = array.ToList<String>();
madatanic
Here's another way: Array.ForEach(array, a => DoSomething(a));
Dave Van den Eynde
I almost want to DV this but technically this is a correct answer however you wouldn't want to do this in practice as this will add a significant amount of overhead to your work as it will need to create a new List<T> and copy the elements over. The extension method approach is much better as it introduces only a method call as the overhead.
Chris Marisic
(It might not even introduce the method call - extension methods seem like prime candidates for the jitter to inline away)
Iain Galloway
An extension method is only syntactic sugar and will translate to a static method that takes the this parameter as the first parameter, just as if you'd remove the "this" keyword from your first parameter in the first place. So the Jitter never sees extension methods as anything special.
Dave Van den Eynde
+2  A: 

Technically, with .NET 3.5, you could do this: (you need to include System.Linq)

IEnumerable<string> a = ...

a.All(i => { DoSomethingWith(i); return true; });
Dave Van den Eynde
A: 

Here is a different version of the .ForEach() extension method that supports exception handling. This will catch all exeptions so you may want to rethrow those you don't handle.

(This was written for use with VS 2010... if you are using previous version you will probably need to remove the = null from the method signature)

public static void SafeForEach<T>(this IEnumerable<T> input,
                                       Action<T> action,
                                       Action<T, Exception> faultAction = null)
{
    if (input == null || action == null)
        return;
    foreach (var item in input)
        try
        {
            action(item);
        }
        catch (Exception ex)
        {
            if (faultAction == null)
                Debug.WriteLine(ex);
            else
                faultAction(item, ex);
        }
}
Matthew Whited