【问题标题】:Why does my state machine throws error: invalid transition?为什么我的状态机抛出错误:无效转换?
【发布时间】:2019-03-16 19:59:45
【问题描述】:

我正在尝试实现状态机。这种情况是,如果提交了文件,则将其发送以供审核,然后获得批准。

但它会抛出一个错误,即已审核 -> 批准转换无效。

这是可能提供更好图片的代码。

为什么会抛出错误?我确保一切都井井有条,但仍然正常。

 public enum ProcessState
    {    
        Submitted,    
        Reviewed,    
        Approved    
    }  

    public enum Command
    {    
        Submit,    
        Review,    
        Approve    
    }   

    public class Process
    {    
        class StateTransition
        {
            readonly ProcessState CurrentState;    
            readonly Command Command;      

            public StateTransition(ProcessState currentState, Command command)
            {    
                CurrentState = currentState;    
                Command = command;    
            }   

            public override int GetHashCode()
            {    
                return 17 + 31 * CurrentState.GetHashCode() + 31 * Command.GetHashCode();    
            }    

            public override bool Equals(object obj)
            {    
                StateTransition other = obj as StateTransition;    
                return other != null && this.CurrentState == other.CurrentState && this.Command == other.Command;    
            }    
        }    

        Dictionary<StateTransition, ProcessState> transitions;

        public ProcessState CurrentState { get; private set; }   

        public Process()
        {    
            CurrentState = ProcessState.Submitted;    
            transitions = new Dictionary<StateTransition, ProcessState>    
            {    
                 { new StateTransition(ProcessState.Submitted, Command.Review), ProcessState.Reviewed },

            { new StateTransition(ProcessState.Reviewed, Command.Approve), ProcessState.Approved },

            };    
        }   

        public ProcessState GetNext(Command command)
        {    
            StateTransition transition = new StateTransition(CurrentState, command);    
            ProcessState nextState;

            if (!transitions.TryGetValue(transition, out nextState))

                throw new Exception("Invalid transition: " + CurrentState + " -> " + command);

            return nextState;    
        }    

        public ProcessState MoveNext(Command command)
        {    
            CurrentState = GetNext(command);    
            return CurrentState;    
        }    
    }    

    public class Program
    {   
        static void Main(string[] args)
        {    
            Process p = new Process();

            Console.WriteLine("Current State = " + p.CurrentState);    
            Console.WriteLine("Command.Submit: Current State = " + p.MoveNext(Command.Submit));    
            Console.WriteLine("Command.Review: Current State = " + p.MoveNext(Command.Review));    
            Console.WriteLine("Command.Approve: Current State = " + p.MoveNext(Command.Approve));    
            Console.ReadLine();  
        }    
    }

更新:

这里是错误部分:

  public ProcessState GetNext(Command command)
        {

            StateTransition transition = new StateTransition(CurrentState, command);

            ProcessState nextState;

            if (!transitions.TryGetValue(transition, out nextState))

                throw new Exception("Invalid transition: " + CurrentState + " -> " + command);

            return nextState;

        }

【问题讨论】:

  • 附加调试器。步行执行和检查状态。计算机是正确的——哪些期望与持有的期望不同?请记住将问题简化为 SSCCE 问题 - 在进行此简化时会发现许多问题。
  • @user2864740:我刚刚做到了。检查谢谢
  • 当然这是“错误部分”,你明确地抛出了一个异常。您是否从某个地方复制了该代码?您是否尝试过调试该代码?
  • 您的transitions 字典不包含Command.Approve 的单个条目。所以它当然会像预期的那样失败。
  • @CamiloTerevinto:我的意思是我已经编辑了那部分。

标签: c# .net c#-4.0 state-machine


【解决方案1】:

这允许您的示例Main 正确运行。问题是您的transitions 字典没有Command.Approve 的条目。

public Process()
{
    CurrentState = ProcessState.Submitted;
    transitions = new Dictionary<StateTransition, ProcessState>
    {
        //This does nothing.  Submitted -> Submitted
        { new StateTransition(ProcessState.Submitted, Command.Submit), ProcessState.Submitted },
        //Submitted -> Reviewed
        { new StateTransition(ProcessState.Submitted, Command.Review), ProcessState.Reviewed },
        //Reviewed -> Submitted.  Do you want this?
        { new StateTransition(ProcessState.Reviewed, Command.Submit), ProcessState.Submitted },
        //I added this.  Reviewed -> Approved
        { new StateTransition(ProcessState.Reviewed, Command.Approve), ProcessState.Approved }
    };
}

输出:

Command.Submit:当前状态 = 已提交

Command.Review:当前状态 = 已审核

Command.Approve:当前状态 = 已批准

请注意,我没有检查您的所有状态机转换。我只是添加了缺少的一个。

【讨论】:

  • 天哪,它正在工作,但你在那里所做的事情超出了我的理解哈哈。能通俗点解释一下吗?
  • @CodingManiac 我在答案的顶部做了。你的状态机没有处理Command.Approve,所以我添加了它。是否允许所有其他状态转换取决于您。我添加的一个允许使用Command.Approve 将某些东西从ProcessState.Reviewed 转到ProcessState.Approved。
  • 很好,但是当我删除第一行时,正如你所说它什么都不做......然后它抛出错误:提交 - >提交无效异常
  • @CodingManiac 这是因为调用了MoveNext(Command.Submit)。这不是必需的,因为状态已经是ProcessState.Submitted。留下第一行并没有什么坏处,但它也没有任何作用。
猜你喜欢
  • 2010-10-26
  • 2020-05-08
  • 1970-01-01
  • 2019-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 1970-01-01
相关资源
最近更新 更多