The blogs are buzzing with continuation support in C# 2.0 and what cool things can be done with it. http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons explains the concept of continuation extremely well. I also found Don Box's posting http://pluralsight.com/blogs/dbox/archive/2005/04/27/7780.aspx very interesting.

Traditionally in languages like C/C++ functions works off the stack. Each function call creates a new frame on the stack in which current context is stored (return address, current stack pointer) and then any arguments to the function is pushed in. The function also creates all its local variables on the stack and pops them off before the function returns. So when the function returns, all information regarding the functions execution is lost. So in case you call the function again it starts from the beginning.

However in continuation this is not what happens. Here the state of the function is preserved and when you call back on the function it starts off from where it left off. All the function locals are allocated on the heap so that their values are preserved when the function is called again. In C# we have a *very* restricted version of continuation using the yield return statement. Even though its restrictive it allows some very cool way of programming.

Here a sample of code where I have a container containing my friends names and I enumerate them.

public class MyContainer
{
    string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" };
    public IEnumerator<string> GetEnumerator()
    {
        for (int index = 0; index < m_friends.Length; index++ )
            yield return m_friends[index];
    }
}

class Program
{
    static void Main(string[] args)
    {
       
MyContainer myContainer = new MyContainer();
        foreach
(string str in myContainer)
            Console.WriteLine(str);
    }
}

You can have multiple enumerators too as in

public class CoolContainer
{
    string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" };
    public IEnumerable<string> straight
    {
        get {
            for (int index = 0; index < m_friends.Length; index++ )
                yield return m_friends[index];
        }
    }
    public IEnumerable<string> Reverse
    {
        get{
            for (int index = m_friends.Length - 1; index >= 0; index--)
                yield return m_friends[index];
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        CoolContainer cc = new CoolContainer();
    
        foreach
(string str in cc.Reverse)
            Console.WriteLine(str);
        
       
Console.WriteLine("----------------");
        
        foreach
(string str in cc.straight)
            Console.WriteLine(str);
    }
}

Seeing all these work I got carried away and tried to do the enumeration without the foreach as in

 

IEnumerator<string> enumerator = myContainer.GetEnumerator();

 

enumerator.MoveNext();

Console.WriteLine(enumerator.Current);

enumerator.MoveNext();

Console.WriteLine(enumerator.Current);           

enumerator.Reset();

           

enumerator.MoveNext();

Console.WriteLine(enumerator.Current);

 

My idea was that after the call to Reset internally I would be able to reach the first element in the list as the index variable will be reset. That’s where I got the surprise in the form of a NotSupportedException in the call to Reset. I send emails to the CSharp user group and found out that its indeed not supported and you need to create new enumerator to go back or if the enumerator once runs till end (i.e. one return is executed) then you’ll automatically get the reset you wanted. This means that iterating twice or more using the same iterator works as in

 

MyContainer myContainer = new MyContainer();
foreach
(string str in myContainer)
    Console.WriteLine(str);
foreach (string str in myContainer)

    Console.WriteLine(str);