【问题标题】:Why does the console.writeline throws error on printing a state? Am I implementing the state machine correctly?为什么 console.writeline 在打印状态时会抛出错误?我是否正确实现了状态机?
【发布时间】:2019-03-16 11:02:47
【问题描述】:

我刚接触状态机,并尝试了使用状态机提交、审查和批准场景的过程。它在fsm.ProcessEvent(FiniteStateMachine.Events.Reviewed); 上抛出错误

即对象引用空异常。我想不通?我是否正确实施了该场景?

    class Program
    {
        static void Main(string[] args)
        {
            var fsm = new FiniteStateMachine();
            Console.WriteLine(fsm.State);
            fsm.ProcessEvent(FiniteStateMachine.Events.Submitted);
            Console.WriteLine(fsm.State);
            fsm.ProcessEvent(FiniteStateMachine.Events.Reviewed);
            Console.WriteLine(fsm.State);
            fsm.ProcessEvent(FiniteStateMachine.Events.Approved);
            Console.WriteLine(fsm.State);
            Console.ReadKey();
        }

        class FiniteStateMachine
        {
            public enum States { Submitted, Reviewed, Approved};
            public States State { get; set; }

            public enum Events { Submitted, Reviewed, Approved};

            private Action[,] fsm;

            public FiniteStateMachine()
            {
                this.fsm = new Action[3, 3] { 
                //Submitted,    Reviewed,               TurnOff,           
                {this.SubmittedForReview,   null,                   null               },     //Submitted
                {null,          this.Reviewing,          null              },     //Reviewed
                {null,          null,                   this.Approving} };       //Approved
            }

            public void ProcessEvent(Events theEvent)
            {
                this.fsm[(int)this.State, (int)theEvent].Invoke();
            }

            private void SubmittedForReview() { this.State = States.Submitted; }
            private void Reviewing() { this.State = States.Reviewed; }
            private void Approving() { this.State = States.Approved; }
        }
    }
}

【问题讨论】:

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


【解决方案1】:

我认为问题出在您的 FSM 上。您正在创建一个多维动作数组。而是尝试查找,就像字典一样。在这里,您有一个字典,其中键是状态,值是您要执行的操作。这对我有用。这就是我所做的更改。

    private Dictionary<int, Action> fsm;

    public FiniteStateMachine()
    {
        this.fsm = new Dictionary<int, Action>() {
        { (int)States.Submitted, SubmittedForReview },
            {(int)States.Reviewed, Reviewing },
            {(int)States.Approved, Approving}
            };
    }

    public void ProcessEvent(Events theEvent)
    {
        var action = fsm[(int)theEvent];
        action.Invoke();
    }

编辑 1

在处理 Reviewed 时获得空引用的原因是 State 设置为 Submitted。 C# 中的枚举从 0 开始,所以当你调用时

 fsm.ProcessEvent(FiniteStateMachine.Events.Reviewed);

你要查找的是什么

 public void ProcessEvent(Events theEvent)
    {
        //this.fsm[(int)this.State, (int)theEvent].Invoke();
        this.fsm[0, 1].Invoke();
    }

因为 this.State 仍处于提交状态。因此,您试图在索引 0 的索引 1 处调用操作,该索引为空。希望对您有所帮助。

【讨论】:

    【解决方案2】:

    在你的情况下,有一个 object reference null exception 是正常的,因为对于你需要的状态 Submitted,你没有 Reviewed 的事件安排你的阵列。

    您可以使用下面的代码来避免对象引用空异常(c# 6 的特性)

        public void ProcessEvent(Events theEvent)
        {
            this.fsm[(int)this.State, (int)theEvent]?.Invoke();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多