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
Odbcconnection Returning Chinese Characters as ""
What Does the @ Symbol Before a Variable Name Mean in C#
Why Can't I Define a Default Constructor For a Struct in .Net
Best Timer For Using in a Windows Service
Where Did Imvcbuilder Addjsonoptions Go in .Net Core 3.0
Jwt Authentication For ASP.NET Web API
How to Find the Number of Cpu Cores Via .Net/C#
I Want to Find the Maximum Frequency of a Common Digit in a Consecutive Subset of Integer Array
How to Display Indirect Data in Jqgrid
Are String.Equals() and == Operator Really Same
How to Create and Connect Custom User Buttons/Controls With Lines Using Windows Forms