为什么字符串常量上的switch-case语句在Visual Studio 2019(16.0.3之前)中需要默认值,而在Visual Studio 2017中则不需要?

问题描述 投票:11回答:2

我正在尝试使用Visual Studio 2017编写的代码库上的Visual Studio 2019,并立即找到构建问题。我有一个switch case语句,其中在一个常量字符串上选择大小写。这没有默认情况,这在Visual Studio 2017中很好,但在Visual Studio 2019中引发了生成错误。

我可以通过添加默认情况来解决问题,但我想避免代码更改,只是在可能的情况下更改编译器设置,以避免需要拉取请求。在任何情况下,理解问题的原因都是很好的。

public class Program
{
    public const string Database = "MongoDB";

    public static string GetDb()
    {
        switch (Database)
        {
            case "MongoDB":
                return Database;
        }
    }
}

可以在https://github.com/martineyles/NoDefaultCase找到包含示例解决方案的github存储库。这包括在将其添加到github之前的状态中的示例解决方案的存档。

在Visual Studio 2017中,构建的输出是:

1>------ Rebuild All started: Project: NoDefaultCase, Configuration: Debug Any CPU ------
1>  NoDefaultCase -> C:\Users\MartinEyles\source\repos\NoDefaultCase\NoDefaultCase\bin\Debug\NoDefaultCase.exe
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

在Visual Studio 2019中,构建的输出是:

1>------ Rebuild All started: Project: NoDefaultCase, Configuration: Debug Any CPU ------
1>C:\Users\MartinEyles\source\repos\NoDefaultCase\NoDefaultCase\Program.cs(9,30,9,35): error CS0161: 'Program.GetDb()': not all code paths return a value
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

我的目标是.net框架4.7.2和默认语言版本。我还尝试将语言版本缩减为C#6.0,并将语言版本手动设置为C#7.3,结果相同。

我正在使用的Visual Studio的特定版本是:

Microsoft Visual Studio Enterprise 2017 
Version 15.9.11
VisualStudio.15.Release/15.9.11+28307.586
Microsoft .NET Framework Version 4.7.03056

Microsoft Visual Studio Enterprise 2019 
Version 16.0.0
VisualStudio.16.Release/16.0.0+28729.10
Microsoft .NET Framework Version 4.7.03056

该问题已解决:

Microsoft Visual Studio Enterprise 2019
Version 16.0.3
VisualStudio.16.Release/16.0.3+28803.352
Microsoft .NET Framework Version 4.7.03056
c# visual-studio-2019
2个回答
8
投票

看起来规范将使用新的可达性规则进行更新,或者这是Roslyn中的一个错误,可能是由于切换表达式引入的更改。

编译器的一个重要问题是方法的结尾是否可达 - 当且仅当switch语句的末尾可达时才会出现这种情况。

ECMA C# 5 standard第13.8.3节描述了switch语句结束的可达性:

如果至少满足下列条件之一,则可以访问switch语句的结束点:

  • switch语句包含一个可到达的break语句,它退出switch语句。
  • switch语句是可访问的,switch表达式是非常量值,并且不存在默认标签。
  • switch语句是可访问的,switch表达式是一个与任何case标签都不匹配的常量值,并且不存在默认标签。

在您的示例中似乎没有这些情况:

  • 没有休息声明
  • switch表达式是一个常量值
  • 常量值与案例标签匹配

因此,使用C#5规则,此switch语句的结束点是不可访问的,它应该编译没有问题。 draft specification in GitHub有相同的文字,所以它看起来并没有改变那里......


0
投票

在C#6中,匹配表达式必须是返回以下类型值的表达式:

一个炭火。 一个字符串。 一个博尔。 一个整数值, 例如int或long。 枚举值。 从C#7.0开始,匹配表达式可以是任何非null表达式。

文档说,使用c#7.0,匹配表达式可以是任何非null表达式。在c#7中,字符串变为可空类型,因此必须添加默认情况(对于null情况)

© www.soinside.com 2019 - 2024. All rights reserved.