Why Is There No Foreach Extension Method on Ienumerable

Why is there no ForEach extension method on IEnumerable?

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:

list.ForEach( item =>
{
item.DoSomething();
} );

Instead of:

foreach(Item item in list)
{
item.DoSomething();
}

The latter is clearer and easier to read in most situations, 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:

  • Type checking: foreach is done at runtime, ForEach() is at compile time (Big Plus!)
  • The syntax to call a delegate is indeed much simpler: objects.ForEach(DoSomething);
  • ForEach() could be chained: although evilness/usefulness of such a feature is open to discussion.

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.

LINQ equivalent of foreach for IEnumerable T

There is no ForEach extension for IEnumerable; only for List<T>. So you could do

items.ToList().ForEach(i => i.DoStuff());

Alternatively, write your own ForEach extension method:

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

Foreach, extension methods, and IEnumerable


So according to the MSDN documentation regarding foreach loop, it implements System.Collections.IEnumerable

No. Anything that supports a GetEnumerator() method that in turn returns an object that supports a bool MoveNext() method and a Current property will support foreach. IEnumerable and IEnumerable<T> both support that and hence everything that implements them will allow for foreach, but it's not the only way. It is though not only a convenient way but also a way that can be used with methods that take an IEnumerable<T> including the linq extension methods, so it's generally best to take that approach when you want to support foreach. (You might choose to also support another means like List<T> does, but it's rarely worth it).

Also, out of curiosity, is a foreach loop more optimized than a for loop in terms of speed?

That's complicated because it's a matter of foreach on what vs for on what. It's common for for to have the edge as it involves a few less virtual calls, but there are exceptions when foreach is faster. For added complication if you were acting directly on an array then foreach would be slower except the compiler actually catches this and rewrites it as a for behind the scenes for you so they are exactly the same.

What does the documentation mean when it says it performs a transform function on each element.

It means that that particular overload of Average passes each element to a call to the selector passed to it. It is the result of this transform that is averaged.

Does this mean the extension method behaves similarly to a foreach loop?

Yes. Indeed they often are foreach. That particular method is a foreach in the .NET Framework version and a slight optimisation upon foreach in the .NET Core version. Many methods are foreach in both versions. Some methods use for in a few cases where it's known to be more performant (see above about how this is sometimes the case and sometimes not). Much of the optimisations that are done wouldn't be worth it in the vast majority of the case, but the Linq methods are heavily used by a lot of people, so the effort to optimise even a little pays off.

The first thread is traversing through this list (foreach) and the second thread is using the Average extension method on this list. So will this cause an exception to be thrown?

In this particular case as long as no thread writes to the list the two will not cause each other any problems. The objects used to implement foreach are created separately in each thread and they are the only objects that mutate. This is not guaranteed by the documentation for List<T>, but unlikely to change.

This does not hold for everything that supports foreach though. There's no promise around multi-threaded foreach except where a given implementation makes it.

why ForEach Linq Extension on List rather than on IEnumerable

List<T>.ForEach() isn't an extension method. It's just a method on List<T>.

One of the main reasons that it isn't available in LINQ (i.e., Enumerable) is that LINQ queries are supposed to be free of side-effects (so you can, e.g., execute a query multiple times and get the same results without changing them), which makes them very composable. All the LINQ operations that accept delegates are for Func; none of them accept an Action delegate.

Why is .ForEach() on IList T and not on IEnumerable T ?

Because ForEach(Action) existed before IEnumerable<T> existed.

Since it was not added with the other extension methods, one can assume that the C# designers felt it was a bad design and prefer the foreach construct.



Edit:

If you want you can create your own extension method, it won't override the one for a List<T> but it will work for any other class which implements IEnumerable<T>.

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

IEnumerable IEnumerable and Extension Method

IEnumerable<T> implements IEnumerable, not vice versa.

Through a bit of runtime hacking, SomeType[] actually does implement IEnumerable<SomeType>. On the other hand, IEnumerable doesn't - and overload resolution is done at compile time, so the compiler has no idea that your IEnumerable items in the collection actually also implement IEnumerable<int>.

If you need to work with IEnumerable, you need to use that in your extension method.

Extension methods not showing even on implementing IEnumerable

It does work. AsParallel is an extension method on IEnumerable. Most extension methods though work on IEnumerable<T>. Your class should start with this:

class myClass : IEnumerable<SomeType>

Or:

class myClass<T> : IEnumerable<T>

(Where T is the type of the generic type argument)


class myClass : IEnumerable<KeyValuePair<int, string>>
{
public Dictionary<int, string> dctIdName = new Dictionary<int, string>();

public myClass()
{
for (int idx = 0; idx < 100; idx++)
{
dctIdName.Add(idx, string.Format("Item{0}", idx));
}

}

// IEnumerable Member
public IEnumerator<KeyValuePair<int, string>> GetEnumerator()
{
foreach (KeyValuePair<int, string> o in dctIdName)
{
yield return o;
}
}

IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}

Now you can call Select for example.

Foreach with Extension Method on IEnumerable


Why result.Add(value) not executed?

This is because LINQ uses deferred execution. Until you actually enumerate the results (the return of Select), the delegates will not execute.

To demonstrate, try the following:

List<int> result = new List<int>();

var list = new List<int> { 1, 2, 3, 4 };

var results = list.Select(value =>
{
result.Add(value);//Does not work??
return value;
});

foreach(var item in results)
{
// Just iterating through this will cause the above to execute...
}

That being said, this is a bad idea. LINQ queries should not have side effects if you can avoid it. Think of Select as a way to transform your data, not execute code.

However this not executed, Another question that is have a way do a foreach on a IEnumerable with Extention Method?

You could write your own extension method:

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

However, I would recommend not doing this. For details, refer to Eric Lippert's post on the subject.



Related Topics



Leave a reply



Submit