Click here to Skip to main content
Click here to Skip to main content

Internals of loops (While, For and ForEach)

, 16 Mar 2011
Rate this:
Please Sign up or sign in to vote.
Internals of loops (While, For and ForEach)

Practically speaking, a loop is the primary building block of a program. We use loop to repeat a set of actions for a certain interval. Now if you think of these intervals, it could be a traversal from one number (called as start index) to another number (called as end index). Very often or probably out of 10 such loops, eight times you loop a collection such that you start from 0 and loop until you point to the end of the sequence.

In C# (and VB.NET) we use while, do-while, for and foreach loop to loop through a set of instructions. In this post, I will try to demonstrate the basic loops for a while and later on take on a bit about foreach loop and its requirement and finally go deep into its internals.

The Basics

C# comes with three basic types of loops.

  1. While Loop: This kind of loop runs while the condition is satisfied.
    while (x >= 0)
    {
    }
  2. do-while: This loop runs at least once while the condition is satisfied.
    do
    {
    
    } while (x >= 10);
  3. for: This loop has three sections, index declaration, condition and increment/decrement section. For each call to the instruction, the index is incremented and checked with the condition.
    for (int i = 0; i < 10; i++)
     {
     }

These are the most basic loops and I hope you already know them and have come across it in your life. .NET introduces another loop called Foreach loop which specially works on an IEnumerable. Each collection in .NET somehow implements IEnumerable and hence can be used as a part of foreach loop. Hence every sequence (or whatever class) when implemented an IEnumerable will have the provision to enumerate through values using foreach.

var enumerable = Enumerable.Range(1, 100);
 foreach (var e in enumerable)
 {

 }

In the above code, the instruction within the scope will loop through until the enumerable has value. Now you might wonder why this interface is at all required? Why do we need to implement it? What exactly happens inside these loops. Let's demonstrate these points.

The Internals

Before going further with the internals of loop, let me clear out one fact which you always remember. Goto is a construct(keyword) in C# that allows you to unconditionally transfer the control from one place to another. The IL equivalent for goto statement is br.s which takes just an instruction line number to transfer the control to a place. Another small instruction brtrue.s which evaluates the loaded object and moves the control to the instruction line only when the evaluated value turns out to be true.

Hence to summarize:

  • br.s -> Unconditionally moves the control
  • brtrue.s -> Moves the control if loaded value is true

Now let's start looking at the internals one by one.

While, do - while Loop

int i=10;
while (x >= 0)
{
}

If you look into the IL instruction set, it creates an integer variable x (which we have declared in code) and a placeholder for boolean variable. The L_0004 instruction is actually a goto equivalent which moves the control over to the location specified. It evaluates and stores the result of equality of x with 0; clt and  ceq specifies the less than and equal respectively.

Based on the result, L_0011 is evaluated and control moves to specified instruction line accordingly.

So basically while loop is a sequence of goto statements between an instruction statements to perform a loop. The instruction between L_0005 - L_0008 is the actual action (one inside curl braces of the loop).

Do-while loop is very similar to while loop, with the only difference being the absence of instruction L_0004, and hence lets it pass through the action.

For Loop

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

The instruction set for the for loop is also very similar to that of while. The for loop creates the index in the first place and stores in zero'th local (L_0002). The goto statement ensures the condition is evaluated and hence moves to L_000b. After the condition is evaluated, the L_0012 sends back the control to L_0005. The L_0005 - L_0006 represents the action block (one inside the curl braces) and eventually after that, it increments the index element by 1 and continues.

We kept the instruction set simple using no code inside the action block. The only difference of  for loop with that of while is the extra instruction to store local index and increment it after the execution of action each time.

For-Each Loop

To understand foreach loop, you first need to understand the basics of IEnumerable. In .NET, a collection implementing IEnumerable must implement a method called GetEnumerator which returns an IEnumerator.

IEnumerator actually represents the cursor which points to a certain logical index of the collection. Let's see the IEnumerator interface.

public interface IEnumerator<out T>
{
    T Current { get; }
    bool MoveNext();
    void Reset();
}

Hence the IEnumerator actually keeps track of the state of the collection, which allows you to use the method MoveNext to point to the next location, Current holds the current value of the collection and Reset allows you to re-initialize the cursor.

IEnumerable on the other hand wraps the enumerator into it such that any collection which implements it, can use the foreach loop. I will discuss in-depth about how to generate Enumerable in my next post.

Now let us take an example to demonstrate what is happening inside a foreach loop:

IEnumerable<int> enumerable = Enumerable.Range(1, 100);
 foreach (int e in enumerable)
 {

 }

The above code actually generates an IEnumerable (collection) of 99 elements from 1 through 100. We loop through the enumerable to get each integer and perform the action on it. Now this is not that simple. Foreach loop is actually broken into the following code after it is been compiled to IL.

var enumerable = Enumerable.Range(1, 100);
IEnumerator<int> enumerator = enumerable.GetEnumerator();
try
{
    while (enumerator.MoveNext())
    {
        int element = enumerator.Current;
        //here goes your action instructions
    }
}
finally
{
    IDisposable disposable = enumerator as System.IDisposable;
    if (disposable != null) disposable.Dispose();
}

I think this looks great to you. Yaah, a foreach loop is actually an abstraction to what we see above. It first finds the enumerator using GetEnumerator from the enumerable, uses MoveNext to loop through the instructions and in the finally block, it tries to dispose the enumerator.

Similar to what I showed in the code above, you can see the IL to correspond to the same rule. The try / finally ensures that enumerator is disposed after the foreach loop is complete or even an exception occurs.

Conclusion

So, as you saw, most of the IL instructions are goto statements, it is not a good idea or not recommended to write goto statement in your code. As suggested, it is fine with goto as soon as the compiler generates this for you, but it will be horrible if the language does consist of a large number of unconditional jumps. So beware.

I hope you like this post, I will continue with IEnumerable in my next post. Stay tuned.

Thank you for reading.

License

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

About the Author

Abhishek Sur
Architect
India India
Did you like his post?
 
Oh, lets go a bit further to know him better.
Visit his Website : www.abhisheksur.com to know more about Abhishek.
 
Abhishek also authored a book on .NET 4.5 Features and recommends you to read it, you will learn a lot from it.
http://bit.ly/EXPERTCookBook
 
Basically he is from India, who loves to explore the .NET world. He loves to code and in his leisure you always find him talking about technical stuffs.
 
Presently he is working in WPF, a new foundation to UI development, but mostly he likes to work on architecture and business classes. ASP.NET is one of his strength as well.
Have any problem? Write to him in his Forum.
 
You can also mail him directly to abhi2434@yahoo.com
 
Want a Coder like him for your project?
Drop him a mail to contact@abhisheksur.com
 
Visit His Blog

Dotnet Tricks and Tips



Dont forget to vote or share your comments about his Writing
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 1 Pinmembervdrielc5-Sep-11 2:32 
GeneralMy vote of 5 PinmemberMrsKatz28-Jan-11 1:38 
GeneralMy vote of 5 Pinmvpthatraja21-Jan-11 17:09 
GeneralRe: My vote of 5 PinmvpAbhishek Sur22-Jan-11 3:26 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140709.1 | Last Updated 16 Mar 2011
Article Copyright 2011 by Abhishek Sur
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid