More .net approach for dynamic state machine

I wrote a simple dynamic FSM. Dynamicmeans that state transitions are dynamic, not static, as shown in ConcreteStateB.

namespace FSM_Example
{
    using System;

    class Program
    {
        static void Main()
        {
            var context = new Context(new ConcreteStateA());
            context.Run();
            Console.Read();
        }
    }

    abstract class State
    {
        public abstract void Execute(Context context);
    }

    class ConcreteStateA : State
    {
        public override void Execute(Context context)
        {
            context.State = new ConcreteStateB();
        }
    }

    class ConcreteStateB : State
    {
        public override void Execute(Context context)
        {
            Console.Write("Input state: ");
            string input = Console.ReadLine();
            context.State = input == "e" ? null : new ConcreteStateA();
        }
    }

    class Context
    {
        private State _state;

        public Context(State state)
        {
            State = state;
        }

        public State State
        {
            get { return _state; }
            set
            {
                _state = value;
                Console.WriteLine("State: " + _state.GetType().Name);
            }
        }

        public void Run()
        {
            while (_state != null)
            {
                _state.Execute(this);
            }
        }
    }
}

This implements a state machine, as described in GoF305.

Since I am new to C # and .net: are there more efficient ways to archive this target using more specific functions from .netor C#?

+5
source share
2 answers

Outcoldman's answer provides many great options.

, FSM , . . Action<T> generic:

public class Context
{
    public Action<Context> State { get; internal set; }

    public Context(Action<Context> state)
    {
        State = state;
    }

    public void Run()
    {
        while (State != null)
        {
            State(this);
        }
    }
}

" " :

public static class SimpleStateMachine
{
    public static void StateA(Context context)
    {
        context.State = StateB;
    }
    public static void StateB(Context context)
    {
        Console.Write("Input state: ");
        var input = Console.ReadLine();
        context.State = input == "e" ? (Action<Context>)null : StateA;
    }
}

, :

var context = new Context(SimpleStateMachine.StateA);
context.Run();
Console.Read();

, , , , :

Action<Context> process = context =>
    {
        //do something
        context.State = nextContext =>
            {
                //something else
                nextContext.State = null;
            };
    };
+5

, , , .

  • . # , .

    interface IState
    {
         void Handle(Context context);
    }
    
  • generics, / State :

    abstract class IState<T>
    {
         void Handle(T context);
    }
    
  • , . , setter State, , DLL, internal.

  • Async , -

    interface IState
    {
         Task HandleAsync(Context context);
    }
    
    class Context
    {
        // ...
    
        public async Task RunAsync()
        {
            while (_state != null)
            {
                await _state.HandleAsync(this);
            }
        }
    }
    
  • , - Rx

+2

All Articles