是否可以在 C# 中限制 public 枚举值?
Is it possible to restrict public enum values in C#?
我目前正在编写一个由展品组成的游览软件程序。展览对象在任何给定点都处于四种状态之一,由 ExhibitStates 枚举定义:
private enum ExhibitState { Ready, Active, Complete, Inactive };
对于要设置展览的开发人员,我希望他们能够选择的只有两种 "starting" 状态:
public enum StartingExhibitState { Ready, Inactive };
目前,我已将其设置为在初始化后,展览将立即设置其状态以匹配其起始状态,如下所示:
switch (startingState) {
case StartingExhibitState.Ready:
SetState(ExhibitState.Ready);
break;
case StartingExhibitState.Inactive:
SetState(ExhibitState.Inactive);
break;
}
今天我发现自己在想这是否是最佳做法。有没有更好的方法来限制哪些枚举选项是 public 哪些是私有的?或者最好只拥有两个单独的枚举?
非常感谢您的宝贵时间。
如果您创建第二个枚举 - 您的意图将通过设置方法的签名得到非常清楚的解释
public enum ExhibitState
{
Inactive = 0,
Active = 1,
Ready = 2,
Complete = 3
};
public enum InitialStates
{
Inactive = ExhibitState.Inactive,
Ready = ExhibitState.Ready
};
public void SetInitial(InitialStates state)
{
SetState((ExhibitState)state);
}
如果您更进一步,您可以添加编译器帮助以防止向方法传递错误的值。
public sealed class InitialState
{
public static readonly InitialState Initial = new InitialState(ExhibitState.Initial);
public static readonly InitialState Ready = new InitialState(ExhibitState.Ready);
public ExhibitState State { get; }
private InitialState(ExhibitState state)
{
State = state;
}
}
构造函数 private
以防止从其他地方实例化 class。
Class 标记为 sealed
以防止派生和更改它的行为。
那么你的方法看起来像
public void SetInitial(InitialState start)
{
SetState(start.State);
}
// use it
SetInitial(InitialState.Initial);
SetInitial(InitialState.Ready);
除非您更改 InitialState
class 的代码,否则无法传递任何其他内容。
您可以使用基于 class 的方法,而不是使用枚举(或其中两个):
public abstract class ExhibitState
{
public static ExhibitInitialState Ready { get { return new ExhibitReadyState(); } }
public static ExhibitInitialState Inactive { get { return new ExhibitInactiveState(); } }
public static ExhibitState Complete { get { return new ExhibitCompleteState(); } }
public static ExhibitState Active { get { return new ExhibitActiveState(); } }
private class ExhibitReadyState : ExhibitInitialState {}
private class ExhibitInactiveState : ExhibitInitialState {}
private class ExhibitCompleteState : ExhibitState {}
private class ExhibitActiveState : ExhibitState {}
}
public abstract class ExhibitInitialState : ExhibitState {}
以上示例显示了一种简单的方法。通常,您不会在 get
方法中创建状态的新实例,而是使用静态实例以便更容易进行比较。
与枚举类似,您仍然可以键入 ExhibitState.Ready
或其他状态。另外,baseclassExhibitInitialState
允许你限制初始可以设置的状态:
public void SetInitial(ExhibitInitialState initState) { ... }
与@Fabio 提出的方法相比,您的好处是不会混淆这些值。此外,与状态特别相关:对于特定状态,行为也应该改变是很常见的。使用这种基于 class 的方法,您可以在特定的 ExhibitState
实现中实现此行为,从而避免许多可能存在于基于枚举的方法中的 switch
语句。
我目前正在编写一个由展品组成的游览软件程序。展览对象在任何给定点都处于四种状态之一,由 ExhibitStates 枚举定义:
private enum ExhibitState { Ready, Active, Complete, Inactive };
对于要设置展览的开发人员,我希望他们能够选择的只有两种 "starting" 状态:
public enum StartingExhibitState { Ready, Inactive };
目前,我已将其设置为在初始化后,展览将立即设置其状态以匹配其起始状态,如下所示:
switch (startingState) {
case StartingExhibitState.Ready:
SetState(ExhibitState.Ready);
break;
case StartingExhibitState.Inactive:
SetState(ExhibitState.Inactive);
break;
}
今天我发现自己在想这是否是最佳做法。有没有更好的方法来限制哪些枚举选项是 public 哪些是私有的?或者最好只拥有两个单独的枚举?
非常感谢您的宝贵时间。
如果您创建第二个枚举 - 您的意图将通过设置方法的签名得到非常清楚的解释
public enum ExhibitState
{
Inactive = 0,
Active = 1,
Ready = 2,
Complete = 3
};
public enum InitialStates
{
Inactive = ExhibitState.Inactive,
Ready = ExhibitState.Ready
};
public void SetInitial(InitialStates state)
{
SetState((ExhibitState)state);
}
如果您更进一步,您可以添加编译器帮助以防止向方法传递错误的值。
public sealed class InitialState
{
public static readonly InitialState Initial = new InitialState(ExhibitState.Initial);
public static readonly InitialState Ready = new InitialState(ExhibitState.Ready);
public ExhibitState State { get; }
private InitialState(ExhibitState state)
{
State = state;
}
}
构造函数 private
以防止从其他地方实例化 class。
Class 标记为 sealed
以防止派生和更改它的行为。
那么你的方法看起来像
public void SetInitial(InitialState start)
{
SetState(start.State);
}
// use it
SetInitial(InitialState.Initial);
SetInitial(InitialState.Ready);
除非您更改 InitialState
class 的代码,否则无法传递任何其他内容。
您可以使用基于 class 的方法,而不是使用枚举(或其中两个):
public abstract class ExhibitState
{
public static ExhibitInitialState Ready { get { return new ExhibitReadyState(); } }
public static ExhibitInitialState Inactive { get { return new ExhibitInactiveState(); } }
public static ExhibitState Complete { get { return new ExhibitCompleteState(); } }
public static ExhibitState Active { get { return new ExhibitActiveState(); } }
private class ExhibitReadyState : ExhibitInitialState {}
private class ExhibitInactiveState : ExhibitInitialState {}
private class ExhibitCompleteState : ExhibitState {}
private class ExhibitActiveState : ExhibitState {}
}
public abstract class ExhibitInitialState : ExhibitState {}
以上示例显示了一种简单的方法。通常,您不会在 get
方法中创建状态的新实例,而是使用静态实例以便更容易进行比较。
与枚举类似,您仍然可以键入 ExhibitState.Ready
或其他状态。另外,baseclassExhibitInitialState
允许你限制初始可以设置的状态:
public void SetInitial(ExhibitInitialState initState) { ... }
与@Fabio 提出的方法相比,您的好处是不会混淆这些值。此外,与状态特别相关:对于特定状态,行为也应该改变是很常见的。使用这种基于 class 的方法,您可以在特定的 ExhibitState
实现中实现此行为,从而避免许多可能存在于基于枚举的方法中的 switch
语句。