如果switch(enum_val)缺少case语句,有没有办法让C#编译器发出错误?

我刚刚意识到我在枚举中的“必须处理”值列表中添加了一个值,但直到运行时我才发现它。 我知道C#编译器在类型的reflection和内省方面非常强大,所以我想知道是否有办法强制switch / case语句覆盖所有可能的enum值?

例:

 enum Colors { Red, Blue, Green, Yellow }; Colors c = ...; switch (c) { case Colors.Red: // No error, Red is a Color break; case Colors.Blue: case Colors.Green: // No error, Blue and Green handled as well break; } // whoops! "error: 'Colors.Yellow' unhandled" // or even, "error: no 'default' and 'Colors.Yellow' unhandled" 

我想要一个编译时的解决方案。

您可以使用SwitchEnumAnalyzer获取此类编译器时间警告。 我只是在我的项目中使用它并且它工作得很好。 与任何Roslyn分析器一样,您可以选择通知级别 – 如果它只是警告或适当的错误。

没有没有编译时间的方法来实现这一点。 然而,非常简单的答案是有一个default处理程序,它只是抛出一个exception,“这个选项没有处理,boo”。

 switch (c) { case Colors.Red: // no error, Red is a Color break; case Colors.Blue: case Colors.Green: // no error, Blue and Green handled as well break; default: throw new Exception("Unhandled option: " + c.ToString()); } 

您可以使用在运行时检查的元方法,但至少检查整个开关。

https://github.com/faisalmansoor/MiscUtil/blob/master/EnumSwitch/EnumSwitch.cs

如果枚举大小,你可以在早期就抛出一个exception,希望在对枚举进行更改时很早就提醒你:

 enum MyEnum {A, B}; class TestEnum { // Static constructor static TestEnum() { // Check if this code needs updating as the enum has changed if (Enum.GetNames(typeof(MyEnum)).Length != 2) { // If this fails update myFunction and the number above throw new Exception("Internal error - code inconsistency"); } } // My function that switches on the enum string myFunction(MyEnum myEnum) { switch (myEnum) { case MyEnum.A: return "A"; case MyEnum.B: return "B"; } throw new Exception("Internal error - missing case"); } } 

如果更改了枚举中​​的项目数,这将从静态构造函数中抛出exception。 所以开发人员知道他需要更新代码。 您甚至可以从与构建一起运行的unit testing中进行此检查。

这是我们在所有解决方案中都需要测试的最佳示例。 您必须编写一个可以枚举Enum的测试并调用包含switch case的方法。 通过此测试,每次编辑枚举时都会出现测试失败,但忘记更新开关案例。

  [Test] public void CheckThatAllEnumCoveredInSwitchCase() { foreach (var singleEnum in Enum.GetValues(typeof(YOURENUM))) { myclass.methodofswitchcase((YOURENUM)singleEnum); } } 

C#编译器没有内置的这个检查,但有.Net的代码合同检查器可以: https : //blogs.msdn.microsoft.com/francesco/2014/09/12/how-to-use -cccheck到certificate,没有案例被遗忘/

该技术是使用代码契约断言来告诉检查器永远不能访问default情况:

 switch (c) { case Colors.Red: break; case Colors.Blue: case Colors.Green: break; default: Contract.Assert(false); // Tell static checker this shouldn't happen } 

然后,如果检查器发现它是可以访问的(因为没有处理其中一个枚举值),它将警告您:

 warning : CodeContracts: This assert, always leading to an error, may be reachable. Are you missing an enum case? 

对于C ++,您可以通过将编译器开关/ we4061添加到项目设置来让编译器发出警告。 希望这可以帮助。 🙂

http://msdn.microsoft.com/en-us/library/thxezb7y.aspx

http://msdn.microsoft.com/en-us/library/96f5t7fy(v=vs.80).aspx

其实我错了; 看来你可以让编译器抛出一个错误。 只需用/ Wall / we4061编译即可。 我自己没有尝试过这个,但是从阅读上面的MSDN页面来看,它看起来应该可行。

只需抛出(双关语),你就可以用字典替换Switch-Case(以Func为例):

 Dictionary> d = new Dictionary>(); d.Add(Colors.Red, (x) => x+1); d.Add(Colors.Blue, (x) => x+1); d.Add(Colors.Green, (x) => x+1); foreach (Colors color in Enum.GetValues(typeof(Colors))) { if (!d.ContainsKey(color)) { throw new Exception("Poor color " + color + " ignored"); } }