为什么console.writeline会在打印状态时抛出错误?我正确实施状态机吗?

问题描述 投票:0回答:2

我刚接触状态机,并尝试使用状态机完成提交,审核和批准方案的过程。它在fsm.ProcessEvent(FiniteStateMachine.Events.Reviewed);上引发错误

即对象引用null异常。我想不出来?我是否正确实施了方案?

    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
2个回答
0
投票

我认为问题在于你的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

处理已审核时获取​​空引用的原因是因为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仍然是Submitted。因此,您尝试在索引0的索引1处调用该操作,该操作为null。希望有所帮助。


0
投票

在你的情况下,有一个对象引用null异常是正常的,因为你没有一个已审查状态的事件已提交你需要安排你的数组。

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

    public void ProcessEvent(Events theEvent)
    {
        this.fsm[(int)this.State, (int)theEvent]?.Invoke();
    }
© www.soinside.com 2019 - 2024. All rights reserved.