考虑以下代码:
private enum myEnum
{
A,
B
}
private void myMethod(myEnum m)
{
switch (m)
{
case myEnum.A:
//do stuff
break;
case myEnum.B:
//do stuff
break;
default:
throw new NotImplementedException(m.ToString());
}
}
如果我向 myEnum 添加第三个成员 C,我只会在运行时收到 NotImplementedException 警告
我想做的是让编译器在存在未处理案例的开关时警告我并且没有默认值:案例。
有没有办法做到这一点,或者有其他解决方案来解决这个问题,最终目标是在编译时警告缺少某些内容?
不幸的是,这里没有编译器功能可以为您执行此操作。
不要使用枚举,而是使用基类或接口。 MyMethod 是在接口上定义的。
每个枚举成员现在都成为 myMethod 具有不同行为的类。 如果您添加一个类(为了扩展选项,目前您需要添加一个枚举项)但不实现 myMethod,您将收到编译器错误。
在代码中有很多地方在 select 语句中提供不同的行为,你可能需要使用多态性。
编辑
我能给出的最好建议是为每个依赖 switch 语句的函数构建单元测试,并为枚举中的每个值调用它(您可以在运行时使用 Enum 类上的 GetValues 成员获取值)
不,语言中没有任何内容可以检查这一点。
您可以拥有:
default:
throw new ArgumentOutOfRangeException("Invalid value or bug");
情况,但显然这是执行时而不是编译时。
从未使用过它,但FxCop可能会有所帮助。它支持编写自定义规则。当然,这不是编译时检查,而是可以集成到您的进程中的东西。
这可能会成为维护的噩梦,必须花费大量时间尝试调试 switch 语句中缺少的枚举值。
编写了一个小类,使 switch 语句更加易于维护,
该类确保所有枚举值都被处理或显式忽略,否则会抛出 NotImplementedExpcetion。
查看源代码和更多详细信息这里
我编写了一个用于在 C# 中执行可区分联合的库,这将是在编译时提供详尽匹配的解决方案。请参阅https://github.com/mcintyre321/OneOf
Install-Package OneOf
它具有用于执行 DU 的通用类型,例如OneOf 一直到 OneOf。其中每个都有一个 .Match 和一个 .Switch 语句,您可以将其用于编译器安全类型行为,例如:
OneOf<A, B> aOrB = GetValue();
aOrB .Switch(
a=> DoSomething(a),
b=> DoSomethingElse(b)
)
您可以使用 JetBrains ReSharper 扩展或 Rider IDE 来执行此检查。
ReSharper 分析将发现某些枚举值未处理或在
default
部分中处理的情况。
要检测未处理值或使用
default
处理值的情况,请参阅:https://www.jetbrains.com/help/resharper/SwitchStatementHandlesSomeKnownEnumValuesWithDefault.html
仅检测没有
default
部分的情况:https://www.jetbrains.com/help/resharper/SwitchStatementMissingSomeEnumCasesNoDefault.html
您可以提高此类情况的严重性以将其报告为错误。您还可以在构建管道中使用免费的 JetBrains InspectCode 工具来检测此类错误,请参阅:https://www.jetbrains.com/help/resharper/InspectCode.html