Too much heat!
First of all let me say that I'm against using extension methods unless I'm adding something important to an existing .NET class.
Alot has been said already, I'm not going to rant about anything, I'm just going to comment on the topic at hand. There are several issues at stake here. First of all in terms of applying a ForEach extension. This could be as simple as:
public static void ForEach<T>(this IEnumerable<T> lst, Action<T> action ){
foreach (var item in lst)
action(item);
}
The way to use such an extension can be as simple as:
var list = Enumerable.Range(1, 100).Select(num => new Node { Left = num, Right = num });
list.ForEach(a => { a.Left += 2; a.Right += 2; });
At a first glance, this is totally correct, it compiles properly. But you will not get the desired effect if you're acting on an IEnumerable, which is the result of the first statement. The extension method on the IEnumerable will not persist the changes inside the list. you could easily test this by debugging the content of list.
What arithma said is incorrect concerning extension methods being primarily for LINQ, they are used everywhere in .NET, but totally correct concerning building an extension methods just to avoid going linear. (although back in 2006 or so i believe, using a delegate used to be more performant than a normal foreach, i'll try to dig the article by Jon Skeet later on). If you're going to build such a thing you might as well yield (ref to arithma's post) the result on every iteration, benefitting from the existing advatanges of the yield keyword (mind you yield does not perform any magic, it will throw in some code in your class and get compiled into IL).
P.S.: This could be achieved without using extensions, but i figured we're in this context...
public static IEnumerable<T> Map<T>(this IEnumerable<T> lst, Action<T> action)
{
foreach (var item in lst)
{
action(item);
yield return item;
}
}
var modified = list.Map(a => { a.Left += 2; a.Right += 2; });
Then again if you look closely at this function you'll notice that it's nothing more than a bastardization of LINQ's Select. So you can achieve the same thing through projection as well as keep the option of providing a parallel approach through TPL if you wish and method chaining.
var modified = list.Select(a => new Node { Left = a.Left + 2, Right = a.Right + 2 });