C#确保有效的枚举值 - Futureproof方法

Joh*_*van 8 .net compiler-construction enums c#-4.0

我正在编写一些带有基于Enum值的简单switch语句的代码.在我看来,在将来某个时候开发人员可能会添加一个新值,所以我在运行时包含了一个默认方法来捕获它并抛出异常.但是我意识到每次输入这样的逻辑时我都应该这样做,并且我只在运行时看到这些问题而不是编译时间.
我想知道是否有一些我可以添加的代码让编译器告诉开发人员他们需要在更新枚举值的情况下更新某些方法 - 除了向枚举本身添加注释之外?

例如(以下示例纯粹是理论上的;我选择了开发生命周期中的状态,以确保它对大多数人来说是熟悉的).

public enum DevelopmentStatusEnum
{
    Development
    //, QA //this may be added at some point in the future (or any other status could be)
    , SIT
    , UAT
    , Production
}

    public class Example
    {
        public void ExampleMethod(DevelopmentStatusEnum status)
        {
            switch (status)
            {
                case DevelopmentStatusEnum.Development: DoSomething(); break;
                case DevelopmentStatusEnum.SIT: DoSomething(); break;
                case DevelopmentStatusEnum.UAT: DoSomething(); break;
                case DevelopmentStatusEnum.Production: DoSomething(); break;
                default: throw new StupidProgrammerException(); //I'd like the compiler to ensure that this line never runs, even if a programmer edits the values available to the enum, alerting the program to add a new case statement for the new enum value
            }
        }
        public void DoSomething() { }
    }
    public class StupidProgrammerException: InvalidOperationException { }
Run Code Online (Sandbox Code Playgroud)

这有点学术性,但我可以看到它有助于使我的应用程序健壮.有没有人在尝试过这方面之前尝试过如何实现这个目标?

提前致谢,

JB

小智 13

在这种情况下,我会尝试不使用枚举,而是使用具有公共静态只读字段的类,这些字段是类的实例.例如,查看.Net框架对颜色的作用.有一个类Color,你可以使用Color.Black,Color.Blue等对象.它们不是常量,但提供几乎所有相同的好处.此外,他们还有常量不具备的其他好处.请参阅C#版本3语言规范,该规范也谈到了这一点.

但这个想法是你没有案例陈述.您为每个"枚举"成员添加了足够的其他属性,方法(DoSomething或其他)可以正确处理它.当另一个开发人员想要添加另一个成员对象时,他需要提供所需的属性.我的例子:我需要一个"枚举"来表示用户可以在系统中执行的不同操作.需要检查这些操作的权限,记录等.我还需要父和子操作(重命名某些内容是"编辑它的一部分"等),用于将操作分组以用于过滤目的的抽象操作,以及特殊操作"所有"和"无"(没有未定义).每个人都需要数据库中的ID和文本.如果某人发明了一种新的动作,我希望它仍然有效.我做的是这样的(为了给你这个想法,省略了许多代码):

  public class Action
  {
    protected Action(bool Abstract, Action Parent, int ID, string Name, bool Undefined)
    { /* snip */ }
    protected Action(bool Abstract, Action Parent, int ID, string Name)
      : this(Abstract, Parent, ID, Name, false)
    { }
    //----------------------------------------------------------------------------------------
    public static readonly Action All = new Action(true, null, 0, "All");
    public static readonly Action None = new Action(false, All, 6, "(Undefined)", true);
    public static readonly Action Modifying = new Action(true, All, 1, "Modifying");
    public static readonly Action Creating = new Action(false, Modifying, 2, "Creating");
    public static readonly Action Deleting = new Action(false, Modifying, 3, "Deleting");
    public static readonly Action Editing = new Action(false, Modifying, 4, "Editing");
    public static readonly Action Exporting = new Action(false, All, 5, "Exporting");
    public static readonly Action Renaming = new Action(false, Editing, 7, "Renaming");
    /* snip */
    //----------------------------------------------------------------------------------------
    /* template for new entries:
    public static readonly Action  = new Action(false, All, , "");
    */
  }
Run Code Online (Sandbox Code Playgroud)

还有更多的行动.并且在其他类中有许多方法可以对操作进行操作.只要每个操作都提供所需的信息,它们都会继续工作.添加动作的开发人员被迫提供信息.如果当前属性不足以进行某些未来的"特殊"操作,则必须在以后添加更多属性.请注意,构造函数是受保护的,因此只有类本身才能创建操作.我在主构造函数中省略了很多代码,用于检查重复的ID和名称以及许多其他内容.您现在可以像这样使用它:

Log.LogAction(Action.Renaming);
Run Code Online (Sandbox Code Playgroud)

LogAction方法中没有case语句.它使用动作的属性.

你的枚举是什么?

问候