试图在C#中实现有限状态机,但不能转换派生类型

时间:2018-06-04 09:45:29

标签: c# templates state-machine

我正在尝试使用上下文类和几个状态类来实现最小状态机。

这里有两个对我很重要的规则:

  1. 上下文类应该没有关于状态类的实现(添加新的状态类不需要更改上下文类)
  2. 状态之间的转换仅在源状态
  3. 上实现

    这里是通用实现:

    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());
        }
    }
    

    现在我尝试将这些类实现为一个真正的应用程序:

    public class CarConfigurationContext : ContextState
    {
        public CarConfigurationContext()
        {
            SetState(new PlayCarState());
        }
    
    }
    
    public class PlayCarState : State<CarConfigurationContext>
    {
        public override void Exit()
        {
            ...
        }
    
        public override void Update()
        {
            ...
        }
    }
    

    我在SetState(new PlayCarState());遇到编译错误 无法从PlayCarState转换为State<ContextState>

    在stackoverflow上搜索之后,一种可能的解决方案是使用接口而不是抽象类,但我希望将我的通用实现保留在ContextState和State中。

    如果您对如何解决这个问题有所了解,同时保持我的概念,我将不胜感激。

    谢谢

    注意:我也有循环引用的问题,但因为我在C#上工作,我还没有想到这个。

    note2:通用实现没有完成,我实际上在考虑哪些方法应该是虚拟的,应该在哪里调用Start和Exit

1 个答案:

答案 0 :(得分:0)

目前我找到的唯一解决方案是将State类的实现更改为PlayCarState:State<ContextState>,然后在Start方法中将ContextState动态转换为CarContextState。这是部分安全和干净,但我想知道是否有更好的解决方案。