Say I have a class:
public class MyClass
{
...
}
and a webservice method that returns an IEnumerable<MyClass>
The consumer of the webservice defines some method:
public void DoSomething(MyClass myClass)
{
...
}
Now, the consumer can call DoSomething
on the result of the webservice method in two ways:
var result = // web service call
foreach(var myClass in result)
{
DoSomething(myClass);
}
or:
var result = // web service call
result.ToList().ForEach(DoSomething);
Needless to say I much prefer the second way since it is much shorter and more expressive (once you get used to the syntax, which I have).
Now, the web service method only exposes an IEnumerable<MyClass>
, but it actually returns a List<MyClass>
which (AFAIK) means that the actual serialized object is still a List<T>
. However, I have found (using reflector) that the Linq method ToList()
makes a copy of all the objects in the IEnumerable<T>
regardless of the actual runtime type (in my opinion, it could just have casted the argument to a List<T>
if it already was one).
This obviously has some performance overhead, especially for large list (or lists of large objects).
So what can I do to overcome this problem, and why is there no ForEach
method in Linq?
By the way, his question is vaguely related to this one.
You can write an extension method but there are good reasons why ForEach is not implemented on IEnumerable<T>
. The second example
result.ToList().ForEach(DoSomething);
copies the IEnumerable into a List (unless it's already a List, I assume) so you're better off just iterating the IEnumerable with good old foreach(var r in result) {}
.
Addendum:
For me, the key point of Eric Lippert's article is that adding ForEach has no benefit and adds some potential pitfalls:
The second reason is that doing so adds zero new representational power to the language. Doing this lets you rewrite this perfectly clear code:
foreach(Foo foo in foos){ statement involving foo; }
into this code:
foos.ForEach((Foo foo)=>{ statement involving foo; });
which uses almost exactly the same characters in slightly different order. And yet the second version is harder to understand, harder to debug, and introduces closure semantics, thereby potentially changing object lifetimes in subtle ways.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With