C#确保有效的枚举值
我正在写一些基于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 { }
这有点学术,但我可以看到它有助于使我的应用程序健壮。 有没有人曾经尝试过/有什么好的想法可以实现?
提前致谢,
JB
在这种情况下,我会尝试不使用枚举,而是使用公共静态只读字段作为类的实例。 例如,看看.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, , "");
*/
}
有更多的行动。 在其他类中有许多操作方法。 只要每个行动都能提供所需的信息,他们就会继续工作。 添加动作的开发人员被迫提供信息。 如果当前属性对于未来某些“特殊”操作不够用,那么稍后必须添加更多属性。 请注意,构造函数是受保护的,所以只有类本身才能创建动作。 我在主构造函数中省略了很多代码,用于检查重复的ID和名称以及其他许多事情。 你现在可以像这样使用它:
Log.LogAction(Action.Renaming);
LogAction方法中没有case语句。 它使用操作的属性。
你的列举是什么?
问候
我找到了使用普通枚举的'解决方案'。 这里是生的,也许可以通过更好的设计来改善:
bool allCasesHandled;
switch (myEnumValue)
{
case MyEnum.Value1:
allCasesHandled = true;
break;
//default:
// allCasesHandled = true;
// break;
}
System.Diagnostics.Debug.WriteLine(allCasesHandled);
如果你尝试编译这个,你会得到一个错误'使用一个未分配的变量'。
维护起来有点麻烦,但对于简单的情况,它可能是有用的,特别是对意图失败的线路发表评论。
我可能是错的,但我不认为,编译器提供了这样的警告。 你可以用一些单元测试来捕获这些问题,这些单元测试用所有可能的枚举值调用上面的方法(对此使用Enum.GetValues())。 每次开发人员添加一个枚举成员并忘记修改所有switch语句时,至少有一个单元测试会失败,并显示“StupidProgrammerException”(顺便说一下:我会抛出一个ArgumentOutOfRangeException)。
链接地址: http://www.djcxy.com/p/16331.html上一篇: C# Ensure Valid Enum Values
下一篇: How to generate multiple parse trees for an ambiguous sentence in NLTK?