0

I am trying to implements a minimal state machine with a context class and several state class.

Here two rules that are important to me:

  1. The context class should have no implementation about state class (adding a new state class doesn't need to change context class)
  2. Transition between states are implemented only on source state

Here the generic implementation:

public abstract class ContextState
{
    protected State<ContextState> currentState;
    public void Update()
    {
        currentState.Update();
    }
    public void SetState(State<ContextState> state)
    {
        currentState = state;
        state.Start(this);
    }
}

public abstract class State<C> where C:ContextState
{
    protected C context;

    public void Start(C context)
    {
        this.context = context;
    }
    abstract public void Update();
    abstract public void Exit();

    protected void SetNewState<S>() where S : State<ContextState>,new()
    {
        Exit();
        context.SetState(new S());
    }
}

Now I try to implements these class to a real application:

public class CarConfigurationContext : ContextState
{
    public CarConfigurationContext()
    {
        SetState(new PlayCarState());
    }

}

public class PlayCarState : State<CarConfigurationContext>
{
    public override void Exit()
    {
        ...
    }

    public override void Update()
    {
        ...
    }
}

I have a compile error at SetState(new PlayCarState()); Impossible conversion from PlayCarState to State<ContextState>

After searching on stackoverflow, one possible solution would be to use interface instead of abstract class but I want to keep my generic implementation in ContextState and State.

If you have any idea on how I could resolve this while keeping the same concept that I have, I would appreciate.

Thank you

note: I have also a problem of circular reference, but because I work on C# I have not yet think about this.

note2: The generic implementation is not finished, I am actually thinking about which methods should be virtual and where should be called Start and Exit

elpha01
  • 196
  • 2
  • 4
  • 19
  • With your current functionality, ` State` could be just ` State`. – bommelding Jun 04 '18 at 10:00
  • No because I need that state holds a reference to a ContextState, but because ContextState is a abstract class I need to specify to State what is the ContextState implementation. This makes sense because State implemations that are not of the same use/Context implementation should not work together. – elpha01 Jun 04 '18 at 10:02

1 Answers1

0

For the moment the only solution I found is to change implementation of State class to PlayCarState:State<ContextState> then make a dynamic cast from ContextState to CarContextState in Start method. This is partially safe and clean but I wonder if there is an even better solution.

elpha01
  • 196
  • 2
  • 4
  • 19