代码之家  ›  专栏  ›  技术社区  ›  sharptooth

当开关不处理一个或多个枚举值时,我可能会出现C#编译时错误吗?[副本]

  •  8
  • sharptooth  · 技术社区  · 10 年前

    假设我有一个 switch 在某个包含枚举的变量上:

    SomeEnum variable;
    switch( variable ) {
       case Option1:
          Magic1;
          break;
       case Option2:
          Magic2;
          break;
       default:
          throw new InvalidOperationException();
    }
    

    我知道 转换 必须处理所有可能的枚举值,以便如果将新值添加到枚举中 转换 必须更改,这就是我添加的原因 default 引发异常。

    问题是在代码运行和控制通过之前没有错误指示 违约 然后抛出异常(顺便说一句,异常很可能在调用堆栈的某个位置被静音)。

    我希望这里有一个编译时错误。例如,Visual C++可以发出 C4062 warning 当没有 违约 并且一个或多个值未处理,并且该警告可以升级为错误。我本可以淘汰 违约 在我的代码中,并利用该警告。

    我可以在C#中使用类似的语言吗?

    1 回复  |  直到 10 年前
        1
  •  12
  •   Jeppe Stig Nielsen    10 年前

    不,您需要编写单元测试。编译器不会为你做这些。

    单元测试可能看起来像:

    public void TestSwitch()
    {
        foreach (var variable in (SomeEnum[])Enum.GetValues(typeof(SomeEnum)))
            Assert.DoesNotThrow(() => YourMethod(variable), "Value {0} not supported", variable);
    }
    

    这取决于您的测试框架。

    实际上,基础整数类型的任何值(例如,如果基础类型为 int 几乎总是这样)是可能的,而且你从来没有写过那么多 case 我想是标签。我知道您只需要带名称的值,但正如我所说,编译器不会为您检查这些值。它只检查两个 案例 参考相同的值。

    我建议你:

    if (!Enum.IsDefined(typeof(SomeEnum), variable))
        throw new InvalidOperationException();
    

    如果枚举没有 [Flags] 属性,但它显然只在运行时工作。