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.