【问题标题】:Can I force a non-exhaustive c# switch expression to cause a compile error?我可以强制使用非详尽的 c# switch 表达式导致编译错误吗?
【发布时间】:2021-07-02 15:24:32
【问题描述】:

我喜欢将枚举映射到值的 switch 表达式 - 虽然不是最具可扩展性的解决方案,但如果枚举表示某种模式(并且不是很大),它会快速且相当干净。

错误的一个常见来源是向枚举中添加成员 - 这通常会使新案例无法处理。

但我认为,如果我们可以为非详尽开关编译错误,这些错误几乎可以消除,从而使遗漏很容易看到和修复。 (默认情况必须省略,否则就没有意义了)

这可能吗?我正在考虑这样的事情:

public string GetTargetValue()
{
    return target switch
   {
       Target.A => "foo",
       Target.B => "bar",
       // Compile error if someone added Target.C, otherwise works fine
       // no default case - it would defeat the point
   };
}

P.S:我主要在 Unity 中工作,但据我了解,较新版本的 Unity 使用 Roslyn 编译器(我不使用 Burst),所以我认为这无关紧要。

【问题讨论】:

  • 就我个人而言,我总是加一个"default" part,然后抛出异常。例如。 _ => throw new ArgumentOutOfRangeException(nameof(direction), $"Unexpected target value '{target}'."),
  • 除了要求有一个“默认情况”在我看来可能是XY problem
  • 枚举可以是基本类型的任何值。它不需要是命名值。就像(Target)5 一样,即使枚举中没有 5 的等价物也可以工作。所以在一个 switch 中强制使用所有有效值似乎非常乏味。
  • 您可以将 CS8524 和 CS8509 添加到项目的“将警告视为错误”部分
  • 警告 CS8524 是专门为捕捉这种模式而引入的(CS8509 适用于不涉及枚举的情况)。让它成为一个错误,你就在那里。

标签: c# roslyn-code-analysis


【解决方案1】:

是的,你可以。

这种情况会引发警告 CS8509,您可以see here。要将其变为错误,请将以下内容添加到您的 .editorconfig:

dotnet_diagnostic.CS8509.severity = error

您可能还想忽略 CS8524,如果您没有默认情况,并且没有引发 CS8509(因此即使您涵盖所有可能的值),see here 也会发生这种情况。在这种情况下,编译器将插入带有throw new SwitchExpressionException(target)的默认情况:

dotnet_diagnostic.CS8524.severity = none

我怀疑您可能需要使用 .NET 5 SDK 进行构建才能生成此警告。

【讨论】:

  • 不幸的是,只要缺少默认情况,似乎就会生成此警告,这意味着无论枚举值如何,编译都会失败。
  • @JonathanLevin 不是吗?如果您包括所有案例,you instead get CS8524。如果你愿意,你可以选择忽略那个。
  • 啊!我检查了你的链接,在每种情况下都看到了类似的警告,错过了它们有不同的代码。看起来这应该可行,谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-01
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-30
相关资源
最近更新 更多