foreach keyword or ForEach<T> 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 (6)

  1. Richard Collette says:

    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.

  2. Simon J Ince says:

    @ Richard,

    Good points – and a balanced approach I think.

    For most code I write, though, the overhead of using delegates/lambdas is worthwhile for code readability… unless they’re used so much that readability actually gets worse, which I guess is the point of the post!

    Simon

  3. MichaelGG says:

    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…

  4. Simon J Ince says:

    @ 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?

    Simon

  5. MichaelGG says:

    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?

Skip to main content