Reputation: 1100
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 ???
Upvotes: 1
Views: 502
Reputation: 186708
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;
...
}
...
}
Upvotes: 4