Click here to Skip to main content
15,884,388 members
Articles / Mobile Apps

For C# - For and For More

Rate me:
Please Sign up or sign in to vote.
2.58/5 (27 votes)
6 May 2005CPOL5 min read 81.3K   21   30
Just moved to C#? Do you miss the for i = 1 to 50 syntax? Look no further, C# can do it too by extending it in a unique way.

Introduction

Just moved to C#? Do you miss the for i = 1 to 50 syntax? Look no further, C# can do it too by extending it in a unique way.

Why more for?

The first question is why? Typically this is only asked by C++ and C# developers. C# developers love their for loop, they say it's elegant, flexible, robust, and that nothing else is needed. I agree on some of their points. It is flexible. It is robust. Technically nothing else is needed, but something else is warranted. As for elegance, well whenever a developer comes to me and says something is elegant, I cringe...

The C style for loop is as follows:

C++
for ([initializers]; [expression]; [iterators])

To count from 1 to 5:

C++
for (int i = 1; i <= 5; i++) 
    Console.WriteLine(i);
}

Now this is all fine and dandy, and it's certainly extensible. The expression and even the iterators can use all kinds of complex evaluators. But in 99% of the cases, a simple int x to y solution is implemented. C# has a foreach, so the usage of the for loop is greatly reduced. In cases where for is still used, it is still primarily used to perform this simple counting function.

For such a simple counting function, the for loop is a bit of overkill syntactically. The problem is that this syntax is a roach point. What is a roach? A roach is a bug that recurs often. A roach point, is a place where roaches breed. Developers moving into C# from other languages very often make mistakes in writing this function. Instead of i <= 5, they write i = 5, or i < 5. A simple mistake, but a very common one. Another common mistake is this - let's use a 0 based loop. 0 to 4 - quick - what changes need to be made to count from 0 to 4? Did you have to think about this *at all*? If so - poof there's room for a roach.

Now C++ developers are quick to jump on me that only a fool would be so stupid as to not understand the syntax. But it's not about understanding this, it's about making mistakes with it. And I consistently see such stupid mistakes made with the for loop that lead to bugs. And while it's certainly higher with those who are new to C#, I have seen the most skilled C++ developers make this novice mistake as well. Roach Point! Now I am not advocating eliminating the beloved C style for - simply offering an alternative so that the C style for is only used when it's needed, which is about 1% of the time.

How for?

Both C# and .NET are wonderfully extensible - something I am eternally grateful for. Using this extensibility, C# can be easily made to support the following syntax:

C#
foreach (int i in new Counter(1, 5)) {
       Console.WriteLine(i.ToString());
}

Neat huh? And guess what - your team won't make any of those stupid mistakes with this format. It can even accept an optional third parameter, step that allows incrementing of, other than 1. I have not implemented reverse counting, but that's easily done as well.

Alternate syntax

Some users object to the use of the new keyword. There is nothing technically wrong with it, just some users find it annoying. By using static methods, the syntax can be changed to:

C#
foreach (int i in Counter.Loop(1, 5)) {
    Console.WriteLine(i.ToString());
}

Either syntax is perfectly acceptable. For my personal use, I've chosen to stay with the new operator. In fact, the class could easily be expanded to support both.

Other Languages

Let's compare this now with the for loop in other languages:

Visual Basic:

VB
for i = 1 to 5

Delphi:

Delphi
for i := 1 to 5 do

Python:

Python
foreach(i in range(1, 5))

At the time I wrote this, I was not aware of the Python syntax. But it bears a striking resemblance.

Drawbacks

It's a tiny tad bit slower. Unless you have a very tight loop with very little code inside of it, there is no measurable difference. If it eliminates even one bug that costs a customer time or money, then I'd say that's worth a picosecond borrowed from each and every one of your customers. I'd certainly be willing to give up a fair number of picoseconds if the software I use on a daily basis was a bit more reliable. Mind you I'm not talking about making applications run slower - but small changes like this will never be noticed in the scheme of things time wise.

It also requires a few more bytes of memory. But I've seen too many programmers come to me and say "look I saved 20 bytes!" and ignoring the fact that their code is more complex, that the program is already 20 Mb, and that they spent 4 hours doing it. Unless we are talking about a few bytes in a large array, yes I would definitely agree these few bytes are worth it. Let's assume its memory footprint is 24 bytes. How many loops are active in a nested fashion at once? Let's imagine your code is deep down in a series of method calls for a total of 10 loops. 10 x 24 = 240. Do you think I care that my .NET app is using 240 more bytes? I doubt you would notice 240 bytes added to a typical Hello World in .NET.

The loss of efficiency pales in comparison. We need not be wasteful of faster CPUs, but as an industry as a whole we should be focusing on more reliable software. Which is what .NET is all about anyways.... Initializing of memory, memory checking, bounds checking, all the things we should have been doing for years.

Code

The code is very simple. The for loop is implemented by making an iterator that returns an integer. If you want another example of extending C# in an interesting way, you can check out Easier database transactions - Extending the using statement to perform automatic database transactions.

C#
public class Counter 
{
    // This enumerator is not thread safe or multi enumerator safe.
    // But its usage pattern does not require such.
    public class CounterEnumerator 
    {
       private Counter _Counter;
       internal CounterEnumerator(Counter aCounter) 
       {
          _Counter = aCounter;
       }
       public bool MoveNext() 
       {
          _Counter._Current += _Counter._Step;
          return _Counter._Current <= _Counter._End;
       }
       public int Current 
       {
          get { return _Counter._Current; }
       }
    }
    private int _Begin;
    private int _End;
    private int _Step;
    private int _Current;

    public Counter(int aBegin, int aEnd) : this(aBegin, aEnd, 1) 
    {
    }
    public Counter(int aBegin, int aEnd, int aStep) 
    {
        _Current = aBegin - 1;
        _Begin = aBegin;
        _End = aEnd;
        _Step = aStep;
    }
    public CounterEnumerator GetEnumerator() 
    {
        return new CounterEnumerator(this);
    }
}

One more Crumb of Food for Thought

C#
for (UInt32 i = mPageCount - 1; i >= 0; i--) {
}

This is a piece of code I came across recently. Did you notice anything wrong with it? Very few readers will. This was attested to by first posting this in a developers forum where only a very few people even noticed that there was a problem, even after I hinted that there was an issue to be found. The above code will not function as the author expected and was the source of a bug that I was tasked with fixing. The correct code is:

C#
for (UInt32 i = mPageCount - 1; i != UInt32.MaxValue; i--) {
}

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Cyprus Cyprus
Chad Z. Hower, a.k.a. Kudzu
"Programming is an art form that fights back"

I am a former Microsoft Regional DPE (MEA) covering 85 countries, former Microsoft Regional Director, and 10 Year Microsoft MVP.

I have lived in Bulgaria, Canada, Cyprus, Switzerland, France, Jordan, Russia, Turkey, The Caribbean, and USA.

Creator of Indy, IntraWeb, COSMOS, X#, CrossTalk, and more.

Comments and Discussions

 
GeneralExtension Methods Pin
Jonathan C Dickinson17-Aug-08 22:53
Jonathan C Dickinson17-Aug-08 22:53 
GeneralRe: Extension Methods Pin
Jonathan C Dickinson17-Aug-08 22:55
Jonathan C Dickinson17-Aug-08 22:55 
GeneralRe: Extension Methods Pin
Chad Z. Hower aka Kudzu18-Aug-08 12:07
Chad Z. Hower aka Kudzu18-Aug-08 12:07 
GeneralC# 2.0 Pin
Marcus Andrén18-May-05 1:36
Marcus Andrén18-May-05 1:36 
GeneralRe: C# 2.0 Pin
Chad Z. Hower aka Kudzu18-May-05 1:51
Chad Z. Hower aka Kudzu18-May-05 1:51 
Generalwtf Pin
Stoyan Damov16-May-05 21:52
Stoyan Damov16-May-05 21:52 
You article was mentioned on (The Daily WTF[^]
I *really* hope it is a joke Smile | :)

I also give you 5 for making my day Smile | :)
GeneralRe: wtf Pin
User 19428917-May-05 5:40
User 19428917-May-05 5:40 
GeneralRe: wtf Pin
Chad Z. Hower aka Kudzu17-May-05 19:47
Chad Z. Hower aka Kudzu17-May-05 19:47 
GeneralRe: wtf Pin
Stoyan Damov20-May-05 17:56
Stoyan Damov20-May-05 17:56 
Generalfor loop Pin
Kevin McFarlane8-May-05 2:25
Kevin McFarlane8-May-05 2:25 
GeneralRe: for loop Pin
Chad Z. Hower aka Kudzu8-May-05 2:28
Chad Z. Hower aka Kudzu8-May-05 2:28 
GeneralRe: for loop Pin
Kevin McFarlane8-May-05 4:20
Kevin McFarlane8-May-05 4:20 
GeneralRe: for loop Pin
Chad Z. Hower aka Kudzu8-May-05 4:59
Chad Z. Hower aka Kudzu8-May-05 4:59 
GeneralRe: for loop Pin
Chad Z. Hower aka Kudzu8-May-05 10:38
Chad Z. Hower aka Kudzu8-May-05 10:38 
QuestionOnly the expression? Pin
Anonymous8-May-05 0:50
Anonymous8-May-05 0:50 
AnswerRe: Only the expression? Pin
Chad Z. Hower aka Kudzu8-May-05 1:19
Chad Z. Hower aka Kudzu8-May-05 1:19 
GeneralRe: Only the expression? Pin
bzBetty8-May-05 10:38
bzBetty8-May-05 10:38 
GeneralRe: Only the expression? Pin
Chad Z. Hower aka Kudzu8-May-05 10:46
Chad Z. Hower aka Kudzu8-May-05 10:46 
GeneralClarity of syntax Pin
StealthyMark7-May-05 7:06
StealthyMark7-May-05 7:06 
GeneralRe: Clarity of syntax Pin
Chad Z. Hower aka Kudzu7-May-05 8:22
Chad Z. Hower aka Kudzu7-May-05 8:22 
GeneralRe: Clarity of syntax Pin
StealthyMark7-May-05 10:51
StealthyMark7-May-05 10:51 
GeneralRe: Clarity of syntax Pin
Chad Z. Hower aka Kudzu7-May-05 11:00
Chad Z. Hower aka Kudzu7-May-05 11:00 
GeneralRe: Clarity of syntax Pin
Chad Z. Hower aka Kudzu7-May-05 21:23
Chad Z. Hower aka Kudzu7-May-05 21:23 
QuestionMore Python in C#? Pin
S. Senthil Kumar6-May-05 20:44
S. Senthil Kumar6-May-05 20:44 
AnswerRe: More Python in C#? Pin
Chad Z. Hower aka Kudzu6-May-05 21:14
Chad Z. Hower aka Kudzu6-May-05 21:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.