Почему console.writeline выдает ошибку при печати состояния?Правильно ли я внедряю конечный автомат? - PullRequest
0 голосов
/ 16 марта 2019

Я новичок в конечных автоматах и ​​попробовал свои силы в процессе отправки, просмотра и утверждения сценариев с использованием конечных автоматов.Выдает ошибку на 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; }
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 16 марта 2019

в вашем случае это нормально, если ссылка на объект пустая исключительная ситуация , потому что у вас нет события для Проверено для состояния Отправлено Вам необходимо организовать массив.

Вы можете использовать код ниже, чтобы избежать ссылка на объект null исключение (функция c # 6)

    public void ProcessEvent(Events theEvent)
    {
        this.fsm[(int)this.State, (int)theEvent]?.Invoke();
    }
0 голосов
/ 16 марта 2019

Я думаю, что проблема с вашим 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 все еще отправлено.Итак, вы пытаетесь вызвать действие по индексу 1 индекса 0, который является нулевым.Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...