for (int i = 0; i < 10; i++)

I can't crisply explain why it drives me nuts to see a for-loop like this in code:

for (int i = 0; i < 10; i++)
{ 
      // Do almost anything on a single line or multiple lines, it's all ugliness, and almost always involves a statement like this:
      if (myArray[i] == somethingelse)
      {
          // do something complicated, and far worse if that affects the array itself
      }
} 

Is it that I instinctively have to scan and remember the bounds? Is it that it forces me to do bounds checking over and over in my own mental loop? is it that it forces me to do mental arithmetic? or is it that I lose track of what the hell is going on in the actual for-loop code because I have to work too hard to understand it all? If you have to get your finger out and trace it down the code on the screen, then it definitely needs refactoring!

(Yes, I've debugged 100's of these kinds of statements in my career, in multiple different languages, and I hated every one of those experiences, if it is to fix a bug, it has almost always been related to fixing the bounds or the indexing syntax!). I instinctively dislike [strongly] for-loops!

 

I'm going to have a go writing a post about this issue as an experiment to see if I can bring that tacit reasoning not to use the for-loop to the forefront of my conscious mind.

It dawned on me recently that I've actually not seen or used this ancient construct in C# code in, what feels like a decade I reckon. This is an ancient feeling in me rising up after being dormant for years.

I recently encountered the dreaded for-loop on several occasions as it has crept into our own codebase recently when pairing with both our budding developers who seem to have no qualms with using it whatsoever. They even use 'i' as the looping variable - straight out of the computer science text books (and probably heaps of stackoverflow answers too). "What else should I you use" they ask?

But the really interesting thing is that even though this construct repels me so viscerally, I can't articulate a convincing argument that will persuade these young guys not to create code with this horrid construct, even if they see others using it in their code base.

The guys must view me as some kind of crazed pedantic for trying so hard to convince them to remove it, since I can't say for sure why it's not so good to use. I think they want to get rid of it just to shut me up, but without seeing anything wrong with its use.

It got me thinking, how do I explain concisely what is so wrong with the dreaded C for-loop construct? How can I communicate that our budding craftswomen/craftsmen entering this craft?

So here goes....

Readability

Just so you know, before we get into it....

I desperately caved at some point in this story and created our own static methods so that theses guys could make their code more readable as a minimal first step to rid our code of the for-loop, if they still insisted on looping some number of times.

The functions looks like this: (can you spot the irony?)

public static class Repeat
{
    public static void This(Action action, int times)
    {
        if (times > 0)
        {
            for (var counter = 0; counter < times; counter++)
            {
                action();
            }
        }
    }

    public static void This(Action<int> action, int to)
    {
        if (to > 0)
        {
            for (var counter = 0; counter < to; counter++)
            {
                action(counter);
            }
        }
    }

    public static void This(Action<int> action, int from, int to)
    {
        if (to > 0
            && from >= 0
            && from <= to)
        {
            var maxCount = (from > 0) ? (to + 1) : to;
            for (var counter = from; counter < maxCount; counter++)
            {
                action(counter);
            }
        }
    }
}

Ironic that I can't write this code without using a for-loop!

I don't think I'd ever want to use this class myself (except perhaps the first overload), but at least the code is a little more readable now perhaps? So, readability has improved, but there is still a big problem with the code used inside this function.

Repeat.This((index) =>
{
    ...whatever you need using an array for, by index x10 
    ...you still use this syntax: myarray[index]
}, 10);

I guess now that I am writing about this, and just put that code usage example in , it shows me my first reason that I have for not liking the for-loop.

(1) The common usage of the for-loop construct results in code that is much harder to read and understand.

Why is that? Because (I think) that you have this indexer into some array, and knowing what that selected array item actually is, is not all that clear or self-describing (by name) in the code. And what's wrong with that? Well in 6 weeks time, am I going to remember what that thing is? Let alone, anyone else on the team coming after me even a hour later, and trying to figure that out!

Enumerables!

The next reason, and possibly the reason I've not used the for-loop ever since LINQ came out, is that I've not had to manipulate arrays of anything since then. Arrays moved on man, to enumerables!

Ever since LINQ came out in C# (circa 2007) I've not had to use arrays ever again. Thank God. I still hated for-loops but now I could avoid them, and their awkward readability entirely, and that's where I've been ever since. 

So, that leads to the next reason not to use for-loops:

(2) It is the 21st century, with LINQ in C#  (or angular/underscore in javascript) you don't need to manipulate arrays directly anymore, use ForEach() instead.

Since, with for-each you get a named variable for each item in the enumerable.

There, that is soooooo much more descriptive and readable than the indexing syntax.  

There is perhaps possibly one case where a for-each construct will not give you what you cleanly want want and force using it is clumsy. (See this stackoverflow post) .That might be when you actually care about the index of the item in the enumerables. Viz: 

var counter = 0;

myCollection.ForEach(item =>
{
    counter++;

    if (item.SomeInt == counter) 
    { 
        ... You have found your item
        return; 
    } 
});

Yep, not hideous but clumsy. Perhaps a for-loop might be appropriate here, perhaps not!

Reuse and Design

One final thought I had when I got this far in the post, and wracking  my brain for the obligatory third reason.

There have been some times when I've noticed the less experienced developers use for-loops to do stuff that is already taken care of better by other libraries or API's. Re-inventing the wheel is always a problem area for the less experienced, but doing stuff manually in a for loop that can be solved with an appropriate library function can sometimes be far more efficient and far more readable and maintainable.

So, for example, replacing all the characters in a string by using a for-loop is clearly a coding horror, and a lot worse than using library functions like string.replace() for example. Or even more robust, use a regex to identify the pattern rather than the character. How many nested for-loops have you seen doing that kind of rubbish?

(3) Use library functions that are optimized for enumerating or comparing items in collections.

OK, well that's all I could think of right now, what do you think?

Do you like for-loops in your code? or do you hate them? Can you tell us why?