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.
December 21, 2007 03:59