2007-12-21 »
Thread-free coroutines in C# 3.0
As I suspected, C# 3.0 has everything we need to accomplish a clone of WvCont from WvStreams in C++. It took a bit of fiddling to figure it out, but the final answer is simple and elegant.
The code below shows a ToAction() extension method that lets you convert any iterator into an Action, so that anywhere a "normal" callback is expected, you can provide a coroutine instead.
We do some non-obvious tricks with variable scoping in ToAction(), but that only has to be written once. The syntax for using it is simple.
using System;
using System.Collections;
using System.Linq;
public static class Example
{
public static Action ToAction(this IEnumerable aie)
{
bool must_reset = false;
IEnumerator ie = aie.GetEnumerator();
return new Action(delegate() {
if (must_reset)
ie = aie.GetEnumerator();
must_reset = !ie.MoveNext();
});
}
static IEnumerable demofunc(string prefix, int start, int end)
{
for (int i = start; i <= end; i++)
{
Console.WriteLine("{0}: {1}", prefix, i);
yield return null;
}
// falling through here is like an extra yield
}
public static void Main()
{
Action a1 = demofunc(" * ", 1, 3).ToAction();
Action a2 = demofunc(" * ", 100, 200).ToAction();
for (int i = 0; i < 10; i++)
{
a1();
a2();
}
}
}
And the output looks like this:
* : 1 * : 100 * : 2 * : 101 * : 3 * : 102 * : 103 * : 1 * : 104 * : 2 * : 105 * : 3 * : 106 * : 107 * : 1 * : 108 * : 2 * : 109
The above program requires Mono 1.2.6 or higher (compile with "-langversion:linq") in Linux, or .NET 3.5 or higher in Windows.
Why would you follow me on twitter? Use RSS.
