C# Events, Finite State Machines, and Generic Delegates

I’ve written a lot of finite state machines over the years, so many times that I’ve gotten quite sick of writing the boilerplate for it.

I’m currently working in C# and Silverlight, so I wanted to put together a decent boilerplate for an FSM that met my needs.

Here are my needs:

  1. My type I use for my “state” variable is typically either an enum or a string. I need my FSM to be flexible enough to handle either.
  2. The C# way of notifying other objects without violating encapsulation is through the use of events and subscriptions to those events.
  3. I must be able to perform stack operations on the state.  Often, a state like the help screen or the menu screen isn’t a state on the state diagram, but rather one that we escape into from any state.
  4. The FSM must not require any sort of interface to be exposed from state classes (this is sort of a restatement of #2, which is to use events).

Here’s the code.

public delegate void StateTransitionDelegate(StateType theNewState);
public class FiniteStateMachine
{
	public event StateTransitionDelegate OnStateStart;
	private StateType state = default(StateType);
	private Stack stateStack = new Stack();
	public StateType State
	{
		get
		{
			return state;
		}
		set
		{
			state = value;
			Refresh();
		}
	}
	public void Refresh()
	{
		if (OnStateStart != null)
		{
			OnStateStart(state);
		}
	}
	public void Push()
	{
		stateStack.Push(State);
	}
	public void PushAndSet(StateType theNewState)
	{
		Push();
		State = theNewState;
	}
	public bool Pop()
	{
		if (stateStack.Count > 0)
		{
			State = stateStack.Pop();
			return true;
		}
		else
		{
			return false;
		}
	}
	public void ClearStack()
	{
		stateStack.Clear();
	}
}

One of the “nagging issues” for me is that the initial state in the FSM is the “default” value of StateType.  In the case of an enum, it’ll typically be the first one defined.

However, when I am constructing my FSM, the event knows nothing of who it should notify, so I cannot tell everyone which state I’m in, even if I wanted to or tried.

This means that I need to do one of the following:

  1. Use a “junk” enum value at the start of the list that indicates “I’m in neutral, or some pre-starting state, uninitialized”, and then later set to a legit useful state value later.
  2. Call Refresh() on the FSM once I’m done setting up the list of notifiers.

Neither of these are a big deal.

The really cool part of this is that the FSM has no concept of the internals of the items who added delegates to the event.  Similarly, the objects that do state changes similarly have no clue how everytnig else in the code works.  In my previous schemes, I often had some sort of IState interface that was needed to make this all work. Yay events!

Advertisements

Tags: , ,

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


%d bloggers like this: