简体   繁体   中英

override enum in derived class in C#

I'm creating an abstract finite machine state class with an enum for the possible commands it can receive, something like:

public abstract class FSMBase
{
    public enum Commands {};
    public enum States;
    public Dictionary<Transition, States> AvailableTransitions;
    public States CurrentState;

    public abstract void InitCommandsAndStatesAndTransitiosnAndInitialState();

    public void ProcessCommand(Commands _command)
    {
        Transition RequestedTransition = new Transition(CurrentState, command);
        if(AvailableTransitions.TryGetValue(RequestedTransition, out State nextState) //pseudocode
        {
             CurrentState = nextState;
        }
    }
}

Then in the derived class I would like to override the States , the Transitions and the Commands . Something like:

public class MyFSM : FSMBase
{
    public override void InitCommandsAndStatesAndTransitiosnAndInitialState()
    {
        States = {Off, starting, started, ...} //HERE IS MY PROBLEM
        Commands = {start, stop, finish, ...}; // HERE IS MY PROBLEM

        Transitions = new Dictionary<Transition, BaseState>
        {
            {new Transition(States.Off, Commands.Start), States.starting},
            ....
        }

        CurrentState = States.Off;
    }
}

How do I override the enum s in my derived class ???

Well, enum is in fact int ( byte , short , long ect.) and can't be overriden. I suggest using generics instead

public abstract class FSMBase<State, Command> 
  where State   : Enum  // : Enum wants C# 7.3+
  where Command : Enum {

  //TODO: I suggest have these fields private, or at least, protected
  public Dictionary<Transition, State> AvailableTransitions;
  public State CurrentState;

  public void ProcessCommand(Command _command) {
    ...
  }

}

When implementing MyFSM you can put required enums:

public class MyFSM : FSMBase<MyStates, MyCommands> {
  ...
}

Edit: in case of lower c# versions you can try same idea but different constraints:

public abstract class FSMBase<State, Command> 
  where State   : struct  
  where Command : struct {

  public State CurrentState;
  ...        

  // Instead of compile time error we are going to have runtime one,
  // if either State or Command is not enum
  static FSMBase() {
    if (!typeof(State).IsEnum)
      throw new InvalidCastException("Generic pararameter State must be enum!");
    else if (!typeof(Command).IsEnum)
      throw new InvalidCastException("Generic pararameter Command must be enum!");
  }
}

...

public class MyFSM : FSMBase<MyStates, MyCommands> {
  public override void InitCommandsAndStatesAndTransitiosnAndInitialState() {
    ...
    CurrentState = MyStates.Off;
    ... 
  }
  ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM