我想在 .NET 8 中切换到 C# 中的详尽切换,以便它能够像某些现代编程语言(Rust,..)一样工作,但我无法让它工作。

我尝试在这里复制答案:

#pragma warning restore CS8509
#pragma warning disable CS8524

string SeverityToString(Severity severity)
{
    switch (severity)
    {
        case Severity.Error:
            return "Error";
        case Severity.Warning:
            return "Warning";
        //default: // default should be automatically generated by pragmas above, isnt it?
        //    throw new InvalidEnumArgumentException(severity.ToString(), (int)severity, severity.GetType());
    }
}

Console.WriteLine(SeverityToString(Severity.Error));

public enum Severity
{
    Warning,
    Error,
}

但无论如何,我仍然会收到编译错误,由于某种原因,编译器不会自动生成默认语句

  Program.cs(5, 8): [CS0161] 'SeverityToString(Severity)': not all code paths return a value

为什么不起作用?为什么编译器不生成默认语句?

2

  • 3
    我可能错了,但据我所知,禁用警告不会自动使代码有效。编译器不会猜测您想要在默认情况下做什么。


    – 

  • 6
    编译错误与警告不同。您可以选择禁用警告,但错误仍然是错误。


    – 


最佳答案
3

您不能忽略编译器错误。如果出现错误,您的代码将无法编译,您必须修复此错误。警告则不同。您可以忽略警告(但这是否明智是另一个问题。我不建议这样做)。

就你的情况而言,当你使用 switch 表达式时,你可以将错误转变为警告。你有一个 switch 语句。将代码重新表述为 switch 表达式:

string SeverityToString(Severity severity)
{
    return severity switch
    {
        Severity.Error => "Error",
        Severity.Warning => "Warning",
        _ => throw new InvalidEnumArgumentException(severity.ToString(), (int)severity, severity.GetType())
    };
}

如果删除最后一行,您将收到编译器警告而不是错误。如果您输入了无效输入,则会抛出 SwitchExpressionException,并显示消息“非详尽的 switch 表达式无法匹配其输入”。

在线演示:

1

  • 不过,我相信您会同意,将某些内容从编译时错误转变为运行时错误绝对是一个糟糕的想法。


    – 

的第二段,它明确指出discard pattern不支持该switch声明。

丢弃模式不能是 is 表达式或 switch 语句中的模式。在这些情况下,要匹配任何表达式,请使用带有丢弃的 var 模式:var _。丢弃模式可以是 switch 表达式中的模式。


正如您已经在使用的那样.NET 8,尝试一下

string SeverityToString(Severity severity)
{
    return severity switch
    {
        Severity.Error => "Error",
        Severity.Warning => "Warning",
        _ => throw new InvalidEnumArgumentException(severity.ToString(), (int)severity, severity.GetType())
    };
}

提供的答案最终让我找到了这个可行的解决方案

将 .editorconfig 添加到解决方案项

内容:

根 = 真

[*.cs]
# exhaustive csharp pattern matching
dotnet_diagnostic.CS8524.severity = none
dotnet_diagnostic.CS8509.severity = error

修改代码如下:

string SeverityToString(Severity severity)
{
    return severity switch
    {
        Severity.Error => "Error",
        Severity.Warning => "Warning",
    };
}

Console.WriteLine(SeverityToString(Severity.Error));

public enum Severity
{
    Warning,
    Error,
}

这样,丢弃运算符(默认情况)就会自动生成,您无需自己编写。如果您添加新的枚举,您将看到编译错误,新的枚举值需要在模式匹配中处理。它真的很好用。

0