[c#] Why is there no ForEach extension method on IEnumerable?

Inspired by another question asking about the missing Zip function:

Why is there no ForEach extension method on the IEnumerable interface? Or anywhere? The only class that gets a ForEach method is List<>. Is there a reason why it's missing, maybe performance?

This question is related to c# .net vb.net extension-methods

The answer is


Partially it's because the language designers disagree with it from a philosophical perspective.

  • Not having (and testing...) a feature is less work than having a feature.
  • It's not really shorter (there's some passing function cases where it is, but that wouldn't be the primary use).
  • It's purpose is to have side effects, which isn't what linq is about.
  • Why have another way to do the same thing as a feature we've already got? (foreach keyword)

https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/


I would like to expand on Aku's answer.

If you want to call a method for the sole purpose of it's side-effect without iterating the whole enumerable first you can use this:

private static IEnumerable<T> ForEach<T>(IEnumerable<T> xs, Action<T> f) {
    foreach (var x in xs) {
        f(x); yield return x;
    }
}

You can use select when you want to return something. If you don't, you can use ToList first, because you probably don't want to modify anything in the collection.


The discussion here gives the answer:

Actually, the specific discussion I witnessed did in fact hinge over functional purity. In an expression, there are frequently assumptions made about not having side-effects. Having ForEach is specifically inviting side-effects rather than just putting up with them. -- Keith Farmer (Partner)

Basically the decision was made to keep the extension methods functionally "pure". A ForEach would encourage side-effects when using the Enumerable extension methods, which was not the intent.


@Coincoin

The real power of the foreach extension method involves reusability of the Action<> without adding unnecessary methods to your code. Say that you have 10 lists and you want to perform the same logic on them, and a corresponding function doesn't fit into your class and is not reused. Instead of having ten for loops, or a generic function that is obviously a helper that doesn't belong, you can keep all of your logic in one place (the Action<>. So, dozens of lines get replaced with

Action<blah,blah> f = { foo };

List1.ForEach(p => f(p))
List2.ForEach(p => f(p))

etc...

The logic is in one place and you haven't polluted your class.


No one has yet pointed out that ForEach<T> results in compile time type checking where the foreach keyword is runtime checked.

Having done some refactoring where both methods were used in the code, I favor .ForEach, as I had to hunt down test failures / runtime failures to find the foreach problems.


You could write this extension method:

// Possibly call this "Do"
IEnumerable<T> Apply<T> (this IEnumerable<T> source, Action<T> action)
{
    foreach (var e in source)
    {
        action(e);
        yield return e;
    }
}

Pros

Allows chaining:

MySequence
    .Apply(...)
    .Apply(...)
    .Apply(...);

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:

// possibly call this "Realize"
IEnumerable<T> Done<T> (this IEnumerable<T> source)
{
    foreach (var e in source)
    {
        // do nothing
        ;
    }

    return source;
}

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.


@Coincoin

The real power of the foreach extension method involves reusability of the Action<> without adding unnecessary methods to your code. Say that you have 10 lists and you want to perform the same logic on them, and a corresponding function doesn't fit into your class and is not reused. Instead of having ten for loops, or a generic function that is obviously a helper that doesn't belong, you can keep all of your logic in one place (the Action<>. So, dozens of lines get replaced with

Action<blah,blah> f = { foo };

List1.ForEach(p => f(p))
List2.ForEach(p => f(p))

etc...

The logic is in one place and you haven't polluted your class.


Note that the MoreLINQ NuGet provides the ForEach extension method you're looking for (as well as a Pipe method which executes the delegate and yields its result). See:


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:

collection.Where(i => i.Name = "hello").Select(i => i.FullName);

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.


You could write this extension method:

// Possibly call this "Do"
IEnumerable<T> Apply<T> (this IEnumerable<T> source, Action<T> action)
{
    foreach (var e in source)
    {
        action(e);
        yield return e;
    }
}

Pros

Allows chaining:

MySequence
    .Apply(...)
    .Apply(...)
    .Apply(...);

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:

// possibly call this "Realize"
IEnumerable<T> Done<T> (this IEnumerable<T> source)
{
    foreach (var e in source)
    {
        // do nothing
        ;
    }

    return source;
}

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)

IEnumerable<string> people = new List<string>(){"alica", "bob", "john", "pete"};
people.Select(p => { Console.WriteLine(p); return p; });

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:

static IEnumerable<T> WithLazySideEffect(this IEnumerable<T> src, Action<T> action) {
  return src.Select(i => { action(i); return i; } );
}

The above code then becomes people.WithLazySideEffect(p => Console.WriteLine(p)) which is effectively equivalent to foreach, but lazy and chainable.


No one has yet pointed out that ForEach<T> results in compile time type checking where the foreach keyword is runtime checked.

Having done some refactoring where both methods were used in the code, I favor .ForEach, as I had to hunt down test failures / runtime failures to find the foreach problems.


Most of the LINQ extension methods return results. ForEach does not fit into this pattern as it returns nothing.


ForEach method was added before LINQ. If you add ForEach extension, it will never be called for List instances because of extension methods constraints. I think the reason it was not added is to not interference with existing one.

However, if you really miss this little nice function, you can roll out your own version

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

One workaround is to write .ToList().ForEach(x => ...).

pros

Easy to understand - reader only needs to know what ships with C#, not any additional extension methods.

Syntactic noise is very mild (only adds a little extranious code).

Doesn't usually cost extra memory, since a native .ForEach() would have to realize the whole collection, anyway.

cons

Order of operations isn't ideal. I'd rather realize one element, then act on it, then repeat. This code realizes all elements first, then acts on them each in sequence.

If realizing the list throws an exception, you never get to act on a single element.

If the enumeration is infinite (like the natural numbers), you're out of luck.


In 3.5, all the extension methods added to IEnumerable are there for LINQ support (notice that they are defined in the System.Linq.Enumerable class). In this post, I explain why foreach doesn't belong in LINQ: Existing LINQ extension method similar to Parallel.For?


While I agree that it's better to use the built-in foreach construct in most cases, I find the use of this variation on the ForEach<> extension to be a little nicer than having to manage the index in a regular foreach myself:

public static int ForEach<T>(this IEnumerable<T> list, Action<int, T> action)
{
    if (action == null) throw new ArgumentNullException("action");

    var index = 0;

    foreach (var elem in list)
        action(index++, elem);

    return index;
}
Example
var people = new[] { "Moe", "Curly", "Larry" };
people.ForEach((i, p) => Console.WriteLine("Person #{0} is {1}", i, p));

Would give you:

Person #0 is Moe
Person #1 is Curly
Person #2 is Larry

If you have F# (which will be in the next version of .NET), you can use

Seq.iter doSomething myIEnumerable


Is it me or is the List<T>.Foreach pretty much been made obsolete by Linq. Originally there was

foreach(X x in Y) 

where Y simply had to be IEnumerable (Pre 2.0), and implement a GetEnumerator(). If you look at the MSIL generated you can see that it is exactly the same as

IEnumerator<int> enumerator = list.GetEnumerator();
while (enumerator.MoveNext())
{
    int i = enumerator.Current;

    Console.WriteLine(i);
}

(See http://alski.net/post/0a-for-foreach-forFirst-forLast0a-0a-.aspx for the MSIL)

Then in DotNet2.0 Generics came along and the List. Foreach has always felt to me to be an implementation of the Vistor pattern, (see Design Patterns by Gamma, Helm, Johnson, Vlissides).

Now of course in 3.5 we can instead use a Lambda to the same effect, for an example try http://dotnet-developments.blogs.techtarget.com/2008/09/02/iterators-lambda-and-linq-oh-my/



One workaround is to write .ToList().ForEach(x => ...).

pros

Easy to understand - reader only needs to know what ships with C#, not any additional extension methods.

Syntactic noise is very mild (only adds a little extranious code).

Doesn't usually cost extra memory, since a native .ForEach() would have to realize the whole collection, anyway.

cons

Order of operations isn't ideal. I'd rather realize one element, then act on it, then repeat. This code realizes all elements first, then acts on them each in sequence.

If realizing the list throws an exception, you never get to act on a single element.

If the enumeration is infinite (like the natural numbers), you're out of luck.


I've always wondered that myself, that is why that I always carry this with me:

public static void ForEach<T>(this IEnumerable<T> col, Action<T> action)
{
    if (action == null)
    {
        throw new ArgumentNullException("action");
    }
    foreach (var item in col)
    {
        action(item);
    }
}

Nice little extension method.


The discussion here gives the answer:

Actually, the specific discussion I witnessed did in fact hinge over functional purity. In an expression, there are frequently assumptions made about not having side-effects. Having ForEach is specifically inviting side-effects rather than just putting up with them. -- Keith Farmer (Partner)

Basically the decision was made to keep the extension methods functionally "pure". A ForEach would encourage side-effects when using the Enumerable extension methods, which was not the intent.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to vb.net

How to get parameter value for date/time column from empty MaskedTextBox HTTP 415 unsupported media type error when calling Web API 2 endpoint variable is not declared it may be inaccessible due to its protection level Differences Between vbLf, vbCrLf & vbCr Constants Simple working Example of json.net in VB.net How to open up a form from another form in VB.NET? Delete a row in DataGridView Control in VB.NET How to get cell value from DataGridView in VB.Net? Set default format of datetimepicker as dd-MM-yyyy How to configure SMTP settings in web.config

Examples related to extension-methods

The operation cannot be completed because the DbContext has been disposed error Extension methods must be defined in a non-generic static class Java equivalent to C# extension methods Razor HtmlHelper Extensions (or other namespaces for views) Not Found Mocking Extension Methods with Moq AddRange to a Collection Distinct() with lambda? Convert string[] to int[] in one line of code using LINQ How do I extend a class with c# extension methods? Static extension methods