Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

I am trying out Visual Studio 2019 on a code base written in Visual Studio 2017, and am immediately finding a build issue. I have a switch case statement in which the case is selected on a constant string. This doesn't have a default case, which is fine in Visual Studio 2017, but throws a build error in Visual Studio 2019.

I can resolve the issue by adding a default case, but I would like to avoid a code change and just change a compiler setting if possible, to avoid the need for a pull request. In any case it would be good to understand the reason for the issue.

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

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

A github repository containing the example solution can be found at https://github.com/martineyles/NoDefaultCase This includes an archive of the example solution in the state before it was added to github.

In Visual Studio 2017, the output of the build is:

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 ==========

In Visual Studio 2019, the output of the build is:

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 ==========

I am targeting .net framework 4.7.2 and the default language version. I have also tried reducing the language version to C# 6.0 and setting the language version manually to C# 7.3 with the same results.

The specific version of Visual Studio I am using are:

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

and

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

The issue is resolved in:

Microsoft Visual Studio Enterprise 2019
Version 16.0.3
VisualStudio.16.Release/16.0.3+28803.352
Microsoft .NET Framework Version 4.7.03056
like image 623
Martin Eyles Avatar asked Apr 05 '19 18:04

Martin Eyles


People also ask

Why do we use default in switch case?

A switch statement can have an optional default case, which must appear at the end of the switch. The default case can be used for performing a task when none of the cases is true. No break is needed in the default case.

Is it necessary to include default case in a switch statement justify?

No..the default statement in switch case is not mandatory. It is an optional case. if the value of the expression does not match with any of the case values,this default statement will be executed (if you write).

Can a switch statement not have a default?

A default clause; if provided, this clause is executed if the value of expression doesn't match any of the case clauses. A switch statement can only have one default clause.

Do you need default in a switch statement C#?

No, the default case is not required. Show activity on this post. From a purely code perspective, there's no requirement to have a default case.


1 Answers

It looks like either the specification will be updated with new rules on reachability, or this is a bug in Roslyn, probably due to changes introduced with switch expressions.

The important question for the compiler is whether the end of the method is reachable - which it will be if and only if the end of the switch statement is reachable.

The ECMA C# 5 standard section 13.8.3 describes the reachability of the end of a switch statement:

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 of these seem to be the case in your example:

  • There are no break statements
  • The switch expression is a constant value
  • The constant value does match a case label

So with C# 5 rules, the end point of this switch statement is not reachable, and it should compile with no problems. The draft specification in GitHub has the same text, so it doesn't look like it's changed there yet...

like image 153
Jon Skeet Avatar answered Nov 02 '22 22:11

Jon Skeet