Let's review the following code which works with generic collection:
List<Tip> tips = new List<Tip>(); //represents a list of Tips
...
//create SiteMapNode from each Tip
foreach (Tip tip in tips)
{
string url = string.Format("{0}/tips/{1}.aspx", appPath, tip.Id);
SiteMapNode node = new SiteMapNode(this, url, url, tip.Title);
node["lastmod"] = tip.PubDate.ToString("u");
AddNode(node, rootNode);
}
Although this code works well we can improve it using Action delegate and List.ForEach method. First we have to exctract code to create SiteMapNode into a method:
private void AddSiteMapNode(Tip tip)
Separating it into a separate method has a few advantages, practically the ability to reuse the same logic for other uses. Now once we have this method creating SiteMapNode's from Tips collection would be:
tips.ForEach(AddSiteMapNode);
P.S. this tip also can be used with Array.ForEach method.
Much more elegant with anonymous delegate
Diego Guidi 11/12/2007 4:40:37 PM
And even more elegant with lambda expressions. listInstance.ForEach(new Action(a=> { string url = string.Format("{0}/tips/{1}.aspx", appPath, tip.Id); SiteMapNode node = new SiteMapNode(this, url, url, tip.Title); node["lastmod"] = tip.PubDate.ToString("u"); AddNode(node, rootNode); }));
Vijay Santhanam 11/12/2007 4:45:03 PM
First, cool tip! I will definitely use this. Diego & Vijay, I believe the whole point of this article is that this allows you to reuse the method, and have it NOT be a cryptic anonymous method. The Action delegate is something I don't think many people have seen before (I know I hadn't).
Mike Duncan 11/12/2007 9:50:15 PM
I would do null checking first before doing the ForEach tips.FindAll(delegate(Tip p1){return p1 != null;}). ForEach(AddSiteMapNode);
Dennis Olano 11/14/2007 2:02:13 AM
Mike you got the point right. Anonymous delegate/lambda expressions are good if you don't have plans to reuse it's code. Regular method is good if you have plans to reuse it. So I think both options are valid but in different cases.
kostya.ly 11/14/2007 4:59:37 PM
You can easily extend this function to work on all IEnumerable classes with an extension method. public static class Extensions { public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) { foreach (T item in source) { action(item); } } }
Cameron MacFarland 1/15/2008 8:22:59 AM
i compared ForEach extension method performance with classic foreach. i did not know that there is such performance difference. i'm really interested using ForEach because of nice flexibility and style, but i found i'll achieve better performance by using it.
Reza Owliaei 2/21/2009 11:15:07 AM