为什么字符串常量上的 switch-case 语句在 Visual Studio 2019(16.0.3 之前)中需要默认值,但在 Visual Studio 2017 中不需要?
Why does a switch-case statement on a string constant require a default in Visual Studio 2019 (prior to 16.0.3) but not in Visual Studio 2017?
我正在 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;
}
}
}
包含示例解决方案的 github 存储库位于
https://github.com/martineyles/NoDefaultCase
这包括示例解决方案在添加到 github.
之前的状态的存档
在Visual Studio2017年,构建的输出是:
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 Studio2019年,构建的输出是:
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 framework 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
In C# 6, the match expression must be an expression that returns a
value of the following types:
a char.
a string.
a bool.
an integral value,
such as an int or a long.
an enum value.
Starting with C# 7.0, the match expression can be any
non-null expression.
文档说在 C# 7.0 中,匹配表达式可以是任何非空表达式。
在 c# 7 中,字符串成为可空类型,因此您必须添加默认大小写(对于空大小写)
看起来 要么 规范将更新有关可达性的新规则,要么这是 Roslyn 中的错误,可能是由于对 switch 表达式引入的更改。
编译器的重要问题是方法的末尾是否可达 - 当且仅当 switch 语句的末尾可达时才可达。
ECMA C# 5 standard 13.8.3 节描述了 switch 语句结尾的可达性:
The end point of a switch statement is reachable if at least one of the following is true:
- The switch statement contains a reachable break statement that exits the switch statement.
- The switch statement is reachable, the switch expression is a non-constant value, and no default label is present.
- The switch statement is reachable, the switch expression is a constant value that doesn’t match any case label, and no default label is present.
None 在您的示例中似乎是这种情况:
- 没有 break 语句
- switch表达式是常量值
- 常量值 确实 匹配个案标签
因此,根据 C# 5 规则,此 switch 语句的终点是 not 可达的,它应该可以毫无问题地编译。 draft specification in GitHub 具有相同的文本,所以它看起来还没有更改...
我正在 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;
}
}
}
包含示例解决方案的 github 存储库位于 https://github.com/martineyles/NoDefaultCase 这包括示例解决方案在添加到 github.
之前的状态的存档在Visual Studio2017年,构建的输出是:
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 Studio2019年,构建的输出是:
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 framework 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
In C# 6, the match expression must be an expression that returns a value of the following types:
a char.
a string.
a bool.
an integral value,
such as an int or a long.
an enum value.
Starting with C# 7.0, the match expression can be any non-null expression.
文档说在 C# 7.0 中,匹配表达式可以是任何非空表达式。 在 c# 7 中,字符串成为可空类型,因此您必须添加默认大小写(对于空大小写)
看起来 要么 规范将更新有关可达性的新规则,要么这是 Roslyn 中的错误,可能是由于对 switch 表达式引入的更改。
编译器的重要问题是方法的末尾是否可达 - 当且仅当 switch 语句的末尾可达时才可达。
ECMA C# 5 standard 13.8.3 节描述了 switch 语句结尾的可达性:
The end point of a switch statement is reachable if at least one of the following is true:
- The switch statement contains a reachable break statement that exits the switch statement.
- The switch statement is reachable, the switch expression is a non-constant value, and no default label is present.
- The switch statement is reachable, the switch expression is a constant value that doesn’t match any case label, and no default label is present.
None 在您的示例中似乎是这种情况:
- 没有 break 语句
- switch表达式是常量值
- 常量值 确实 匹配个案标签
因此,根据 C# 5 规则,此 switch 语句的终点是 not 可达的,它应该可以毫无问题地编译。 draft specification in GitHub 具有相同的文本,所以它看起来还没有更改...