Big Ball of Mud

Creating simple state machines using C# 2.0 iterators

with 4 comments

State machines can be a very useful way of simplifying complex logic: sometimes they are part of the business domain, sometimes the can help us managing screen logic. Normally you would use a State pattern for this, but when you have a simple case of sequential states and there is not much action with it, you end up with with creating lots of small state classes, which just change the state to the next one.

Recently when studying C# iterator blocks in depth, I discovered that we already have a mechanism  for state management built-in: iterators.

Let me show you an example with a simple lamp object: lamp can be On or Off and we change the state by switching it, it can also print its state to the console.

   26     public enum LampState
   27     {
   28         On,
   29         Off
   30     }
   31
   32     public class Lamp : StateMachine<LampState>
   33     {
   34         public void Switch()
   35         {
   36             Console.WriteLine("Switching...");
   37             Go();
   38         }
   39
   40         public void PrintState()
   41         {
   42             Console.WriteLine("Current state: " + CurrentState);
   43         }
   44
   45         protected override IEnumerable<LampState> ConfigureStates()
   46         {
   47             while (true)
   48             {
   49                 yield return LampState.Off;
   50                 yield return LampState.On;
   51             }
   52         }
   53     }

The combination of ConfigureStates and Go methods do the trick. ConfigureStates stops its execution at yield return points and changes the state of the lamp. Go method advances the iterator, resumes the execution from the last point and goes to the next yield return. Clearly this approach gives the possibility to think about state changes in more sequential way. Let’s run it:

    6     class Program
    7     {
    8         static void Main()
    9         {
   10             var lamp = new Lamp();
   11             lamp.Start();
   12
   13             lamp.PrintState();
   14             lamp.Switch();
   15             lamp.PrintState();
   16             lamp.PrintState();
   17             lamp.Switch();
   18             lamp.PrintState();
   19
   20             Console.ReadLine();
   21         }
   22
   23     }

The result is:

        Current state: Off
        Switching...
        Current state: On
        Current state: On
        Switching...
        Current state: Off

And finally the mysterious base class:

   56     public abstract class StateMachine<TState>
   57     {
   58         private IEnumerator<TState> _enumerator;
   59
   60         public void Start()
   61         {
   62             _enumerator = ConfigureStates().GetEnumerator();
   63             _enumerator.MoveNext();
   64         }
   65
   66         public TState CurrentState
   67         {
   68             get { return _enumerator.Current; }
   69         }
   70
   71         protected void Go()
   72         {
   73             _enumerator.MoveNext();
   74         }
   75
   76         protected abstract IEnumerable<TState> ConfigureStates();
   77     }

And that’s it! The rest is done by the compiler. The magic behind this works because iterator blocks are in fact a form of coroutine, and couroutines and state machines are in very close relationship.

I definitely declare iterator blocks #1 feature in C#.

About these ads

Written by bigballofmud

2009/03/21 at 12:27 am

Posted in C#

4 Responses

Subscribe to comments with RSS.

  1. Creating simple state machines using C# 2.0 iterators…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

    DotNetShoutout

    2009/03/21 at 12:37 am

  2. [...] Creating simple state machines using C# 2.0 iterators Posted: Mar 25 2009, 09:05 PM by DigiMortal | with no comments Filed under: ASP.NET, C#, SharePoint, Links, MVC [...]

  3. Just out of interest, how would you change the state non-sequentially at run time.

    In other words how would you implement

    SetState(T state)

    ??

    LaughingJohn

    2009/04/01 at 1:50 pm

    • I’m afraid this is tricky with this approach: you cannot restart the iterator block “in the middle” (in a sort of goto fashion). The only way I know to emulate this is serializing the enumerator and then deserializing it back, so that it remembers the last yield.

      You can still take advantage of the iterator approach in some scenarios which do not require persisting the current state and bringing it back, for example: driving a windows form states (like in some complicated wizards), where state machine lives with the form object and always starts from the beginning. You can have a nice implementation of some really complicated state transitions this way. If this is not your case – go with the State pattern.

      bigballofmud

      2009/04/01 at 9:09 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: