foreach keyword or ForEach extension method?
Is this a question of taste, or something more serious? [Warning: this post won’t change your life J]
I found myself writing the following extension method yet again the other day;
public static void ForEach<T>(
this IEnumerable<T> source,
Action<T> action)
{
foreach (T item in source)
{
action(item);
}
}
This means I can write simple (contrived) code like the following;
entities.ForEach<ObjectDefinition>(o => o.DeleteDbRecord());
This will enumerate all my ObjectDefinition objects and call DeleteDbRecord on each. But why didn’t I just write it like this?
foreach (ObjectDefinition o in entities)
{
o.DeleteDbRecord();
}
I’ve raised this because some code I’ve seen (and written!) has reached a saturation point, where lambdas, extension methods, and other concepts have taken over - meaning the code looks more like it was written in LISP than C#.
But does that matter?
A quick search shows there are all sorts of discussions about this online, which is interesting. It is actually quite an old discussion now!
Comments
Anonymous
April 27, 2009
From a performance standpoint it matters. Lambdas are essentially delegates and do not perform as well as a normal loop structure. Test it. At best you're only saving a few keystrokes, maybe none depending on what intellisense does for you between the two versions. This is trying to solve a problem that doesn't exist. I will admit that I sometimes take the slight performance hit and Linq/Lambdas when it makes the code more readable. But in critical loops and where the Linq code may actually read more complex, I will use a normal loop construct.Anonymous
April 27, 2009
PingBack from http://asp-net-hosting.simplynetdev.com/foreach-keyword-or-foreach-extension-method/Anonymous
April 27, 2009
The comment has been removedAnonymous
April 27, 2009
I'm lucky I guess that most of my perf can be found with better algorithms. I can only recall a few times where the overhead of delegate invocation was an issue, and once of those was a bug in the CLR. foreach has overhead too, versus a for loop and manual indexing. Maybe the compiler optimizes it on some types, but I don't believe it does on any IList. In F#, I write much less efficient code, and it's very rarely a problem. If I do profile and find a certain path is slow, fine, move back to mutables and even pointers if necesary. But I highly doubt that many people work in application where these sort of optimizations are needed all the time...Anonymous
April 27, 2009
@ Michael; Ditto - every now and then some code needs low level tuning, but I prioritise maintainability first by default... generally it is architectural decisions that impact perf more in the fields I do most work in. But what's interesting is that you use F# - so you're used to the functional paradigm... as am I from quite some time ago, but others may not be. I wonder if this makes you (and I) more accepting of lambdas etc as programming constructs as it is just a natural fit? SimonAnonymous
April 27, 2009
F# introduced me to the functional mindset, but before I could use F#, I had a couple of years of full time C# (and still have a lot of C# still). The fact C# came out with a nice intro FP feature set with 3.0 was a sanity-saving bonus :). Personal experience tells me as soon as a C# programmer "gets it" -- they grasp they can toss around functions -- they tend to love it and use it tons. Anyone who likes LINQ is pretty much validating that, don't you think?