…or “Short rant on why C-style for-loops are almost always unnecessary “…

If you’ve been with C# for the last couple of years, your coding style has probably evolved in a more functional direction since the introduction of C# 3/.NET 3.5 with all its LINQ and lambda goodness.

In my own code, I have almost completely dismissed the old C-style for-loop in favor of .Select, .Where etc., making the code way more readable and maintainable.

The readability and maintainability is improved because long sequences for for/foreach and collection-juggling can now be replaced by oneliners of selection, mapping, and projection.

One place, however, where I often see the for-loop used, is when people need to build sequences of repeated objects, or where some variable is incremented for each iteration.

Now, here is a message to those developers: Please realize that what you actually want to do is to repeat an object or map a sequence of numbers to a sequence of objects.

Having realized that, please just implement it like that:

Same thing goes for sequences of elements where something is incremented:

There’s just too many for-loops in the world!

Not the same thing, but still somehow related to that, is when people need to collect stuff from multiple properties and ultimately subject each value to the same treatment – please just implement it like that:

</rant>

How to loop good

5 thoughts on “How to loop good

  • 2010-12-28 at 13:32
    Permalink

    Agreed. However keep in mind that while projections are good for Queries, they are less suitable for Commands. Whenever I need to iterate over a sequence and make each element do something, I find it more readable to use a ‘foreach’ block.

    As an example, I’m currently looking at this piece of code (where behaviors is a result of a projection):


    foreach (var b in behaviors)
    {
    b.Assert(setProperty);
    }

    Alternatively, I could have written the above as


    behaviors.ToList().ForEach(b => b.Assert(setProperty));

    It produces the same end result, but it’s less apparent that we’re changing the state of something. It kind of ‘drowns’ a little in the rest of the LINQ code…

    Reply
  • 2010-12-28 at 13:55
    Permalink

    Just keep in mind that Enumerable.Repeat doesn’t create a number of objects. Instead it creates a sequence, that will return a reference to the same instance a number of times when iterated.

    Reply
  • 2010-12-28 at 15:09
    Permalink

    @Mark: I don’t know if I agree with that one.

    I know that it conflicts with the functional look-and-feel of LINQ to top off a ginormous query with a .ForEach and start changing the world, but I don’t have any problems with that if the code is otherwise clear and readable.

    Reply
  • 2010-12-28 at 15:11
    Permalink

    @Brian: Thanks for pointing that out šŸ™‚

    If multiple instances are required, Enumerable.Range(0, 5000).Select(i => new InstanceOfSomething()) will do.

    Reply
  • 2010-12-28 at 15:18
    Permalink

    @Brian:

    Yes, but you can always use Enumarable.Repeat with a Func to produce a sequence of new instances:


    Enumerable.Repeat<Func>(() => new Foo(), 5000).Select(f => f());

    @mookid:

    Sure, YMMV.

    I actually used to think like you, then read this blog post by Eric Lippert and changed my mind.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: