在 C# 中覆盖派生 class 中的枚举
override enum in derived class in C#
我正在创建一个 abstract
有限机器状态 class 和一个 enum
用于它可以接收的可能命令,例如:
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;
}
}
}
然后在派生的 class 中,我想 覆盖 States
、Transitions
和 Commands
。类似于:
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;
}
}
如何覆盖派生的class中的enum
???
好吧,enum
实际上是 int
(byte
、short
、long
等等)并且不能被覆盖。我建议改用 generics
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) {
...
}
}
实施 MyFSM
时,您可以放置所需的枚举:
public class MyFSM : FSMBase<MyStates, MyCommands> {
...
}
编辑: 如果是 较低的 c# 版本,您可以尝试相同的想法但不同的约束:
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;
...
}
...
}
我正在创建一个 abstract
有限机器状态 class 和一个 enum
用于它可以接收的可能命令,例如:
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;
}
}
}
然后在派生的 class 中,我想 覆盖 States
、Transitions
和 Commands
。类似于:
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;
}
}
如何覆盖派生的class中的enum
???
好吧,enum
实际上是 int
(byte
、short
、long
等等)并且不能被覆盖。我建议改用 generics
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) {
...
}
}
实施 MyFSM
时,您可以放置所需的枚举:
public class MyFSM : FSMBase<MyStates, MyCommands> {
...
}
编辑: 如果是 较低的 c# 版本,您可以尝试相同的想法但不同的约束:
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;
...
}
...
}