Inspired by another question asking about the missing Zip
function:
Why is there no ForEach
extension method in the Enumerable
class? Or anywhere? The only class that gets a ForEach
method is List<>
. Is there a reason why it's missing (performance)?
There is already a foreach statement included in the language that does the job most of the time.
I'd hate to see the following:
Instead of:
The latter is clearer and easier to read in most situation, although maybe a bit longer to type.
However, I must admit I changed my stance on that issue; a ForEach() extension method would indeed be useful in some situations.
Here are the major differences between the statement and the method:
Those are all great points made by many people here and I can see why people are missing the function. I wouldn't mind Microsoft adding a standard ForEach method in the next framework iteration.
You could write this extension method:
Pros
Allows chaining:
Cons
It won't actually do anything until you do something to force iteration. For that reason, it shouldn't be called
.ForEach()
. You could write.ToList()
at the end, or you could write this extension method, too:This may be too significant a departure from the shipping C# libraries; readers who are not familiar with your extension methods won't know what to make of your code.
You could use the (chainable, but lazily evaluated)
Select
, first doing your operation, and then returning identity (or something else if you prefer)You will need to make sure it is still evaluated, either with
Count()
(the cheapest operation to enumerate afaik) or another operation you needed anyway.I would love to see it brought in to the standard library though:
The above code then becomes
people.WithLazySideEffect(p => Console.WriteLine(p))
which is effectively equivalent to foreach, but lazy and chainable.I wrote a blog post about it: http://blogs.msdn.com/kirillosenkov/archive/2009/01/31/foreach.aspx
You can vote here if you'd like to see this method in .NET 4.0: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=279093
So there has been a lot of comments about the fact that a ForEach extension method isn't appropriate because it doesn't return a value like the LINQ extension methods. While this is a factual statement, it isn't entirely true.
The LINQ extension methods do all return a value so they can be chained together:
However, just because LINQ is implemented using extension methods does not mean that extension methods must be used in the same way and return a value. Writing an extension method to expose common functionality that does not return a value is a perfectly valid use.
The specific arguement about ForEach is that, based on the constraints on extension methods (namely that an extension method will never override an inherited method with the same signature), there may be a situation where the custom extension method is available on all classes that impelement IEnumerable
<T
> except List<T
>. This can cause confusion when the methods start to behave differently depending on whether or not the extension method or the inherit method is being called.If you have F# (which will be in the next version of .NET), you can use
Seq.iter doSomething myIEnumerable