torsdag 16 oktober 2008

The ForEach extension method (C#)

Everyone knows about the foreach keyword, but have you ever noticed there are no equivalent extension method for IEnumerables? I.e. execute "this action" on each element. Perhaps the most simple extension method of them all, which is the reason I'll share it with you :)

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

For you who aren't familiar with extension methods, what it really says is that, ForEach is a member method of IEnumerable<T>, and can be called by simply writing
myList.ForEach(myAction)

For example, to output each item of a list to the console, you could write:
myList.ForEach(x => Console.Write(x));

instead of
foreach(var x in in myList) Console.Write(x);

In this case you might not gain so much in terms of code size, but I think it makes the code more readable. You are reading text from left to right, so it makes sense having the for each statement to the right, right? :)
myList.WhereThis().SelectThat().DoThis();

(There is probably some kind of cool name for this pattern, like "The opposite of law of demeter"... Gustaf probably has more knowledge in this!)

Here is a more complex example of a combination of extension methods:
myList.Where(x => x.IsValid()).Select(x => x.ComputeValue()).Where(x => x > 0).ForEach(x => Console.Write(x));

Where and Select are also extension methods of IEnumerable. Without these you would have to write:

foreach(var x in myList)
{
if (x.IsValid())
{
var value = x.ComputeValue();
if (value > 0) Console.Write(value);
}
}

8 lines instead of 1! Impressed? :)

So, extension methods! Learn them, use them, and write your own!

9 kommentarer:

peteter sa...

Your select-thingie there looks like something you do in Linq?

ForEach is in Generic List yaa?

Christian Genne sa...

Yes! I'm not clear of what's part of Linq and what's not, but I guess the Select and Where extension methods are part of Linq?! I always thought Linq was about writing

from x in myList select x.Value;

and that Select and Where are just new extension methods, but probably Linq is also:

myList.Select(x => x.Value);

Might be that extension methods are a part of Linq?!

ForEach is part of generic list yes, or more correctly, generic IEnumerable (doesn't have to be a list, just have to be something you can enumerate!)

peteter sa...

I have really no idea of what Linq is or not :-) What I tried to 'ask' was, if what you tried to do in your code example isn't something that you normally do in Linq? - but then it probably would like a little different, but still very similar.

The other thing; I didn't really understand why you would add your extension method in the first place, if it's already there?

Anonymous sa...

I tried the code you provided but it would not compile the below compiled.

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

Christian genne sa...

peteter, sorry I forgot to answer ur comment... If u have not already figured the answer out, here it is :)

ForEach is there because I wrote it, not because it's part of .net. Try using system.linq, u will see there is no such function there.

Anonymous, what doesn't compile? What error do u get?

Anonymous sa...

The code you originally provided doesn't compile. The error is "The type or namespace name 'T' could not be found".

Your code omits the <T>after the method name.

Christian Genne sa...

Ah, < and > doesn't work well with web browsers, forgot to escape them. I've updated the post. Thanks for notifying me!

D. Patrick Caldwell sa...

Hey, I enjoyed your blog post. The syntax you mentioned would be called a fluent interface I believe. I've been writing a lot of extension methods lately. I love them and I love the topic.

Also, I was wondering if you've tried any syntax highlighters? I use one from google code and I have a pretty easy one liner you can add to your template. If you'd like to use it, feel free.

Christian Genne sa...

Hi, and thanks for your comment! I've read all of your extension method posts as well, very nice! Extension methods makes your life easier, don't they? :)

I actually have a syntax highlighter setup on this blog, looks like the same you are using, but for some reason I had forgotten to tag my code. I've updated the post now!

Keep on blogging about extension methods!