3
public enum Test { Yes, No }

I have these two switch expressions. The one below gives a CS8509 warning:

Test? test = null;
var result = test switch
{
    null => "Null",
    Test.Yes => "Yes",
    Test.No => "No",
};

But moving the null case to the end resolves it. Does anybody know why this happens? This has to be a bug, correct?

Test? test = null;
var result = test switch
{
    Test.Yes => "Yes",
    Test.No => "No",
    null => "Null",
};

Project settings:

<PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <LangVersion>10.0</LangVersion>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <NoWarn>8524</NoWarn>
</PropertyGroup>
GSerg
  • 76,472
  • 17
  • 159
  • 346
Xiaoguo Ge
  • 2,177
  • 20
  • 26
  • 3
    Moving it to the end *shouldn't* resolve it. [I cannot reproduce](https://sharplab.io/#v2:CYLg1APgAgTAjAWAFDKnAbAAigFkwMQAoAVAUwGcAXAfk0osoEpMBvZTDzANwEMAnTHwoBXADaVMAXjoNM5AO4BLSgGMAFuzZJOHMlQB0ATQpSAfJgBEx8hYA07HXsr6AcgHszl93YecAdmKinhYugT7aAL4A3MgRyKgAzJikAQC2mE6smNa2mO6YEUA). – Sweeper May 24 '23 at 23:43
  • @Sweeper I've added my project settings – Xiaoguo Ge May 24 '23 at 23:47
  • An enum should never be nulled - that's the reason you have an enum. Either start your enum with the option "Unknown" (ergo: defaulting to I do not know) or some other option which should be default, but null should never be a viable option – riffnl May 24 '23 at 23:49
  • @riffnl Thanks for the comment but that's not the question though – Xiaoguo Ge May 24 '23 at 23:54
  • @XiaoguoGe my question is, why do you check for null in the first place? – riffnl May 24 '23 at 23:56
  • @riffnl Because OP forgot to mention that `test` is of type `Test?` – Sir Rufo May 24 '23 at 23:58
  • @riffnl @Sweeper Just realized I missed one line of code in the question. `test` is defined as nullable intentionally to demonstrate the problem. – Xiaoguo Ge May 24 '23 at 23:58
  • 1
    Not sure if this is a bug. [This](https://github.com/dotnet/roslyn/issues/47066) is probably a better place to ask though. – Sweeper May 25 '23 at 00:06
  • 1
    This compiler will raise a warning in any case. CS8509 if null is on top or CS8524 if null is at bottom. Both warnings describe nearly the same – Sir Rufo May 25 '23 at 00:10
  • Why do you have `8524`? – Martin Smith May 25 '23 at 00:23
  • @MartinSmith because it defeats CS8509. I want 8509 more than I do 8524 – Xiaoguo Ge May 25 '23 at 00:24
  • @GuruStron I can reproduce this on two compiler versions: 4.4.0-6.23101.15 (72dbad1d) and 4.6.0-3.23259.8 (c3cc1d0c) – Xiaoguo Ge May 25 '23 at 00:25
  • 3
    @Sweeper [repro](https://sharplab.io/#v2:CYLg1APgAgTAjAWAFDIMQAcBOBDA5gW2wAIB3bTAOwEsLcjgqBnbAIwBsBTIgYQGUAOAKwwALMihwAbESgiiAMQAUAFQ6MALgH4i6teoCURAN7IiZogDdyRTGoCubdUQC8OvUUYkq6gMYALUxMkczNVDQA6AE01FwA+IgAiaMYEgBpTELD1cIA5AHs4xPy0jPMKBzZChJyKkuCAXwBuZHrkcQBmIg5y/CIs4yJk1KJ8onqgA) – Guru Stron May 25 '23 at 00:31

1 Answers1

4

Found this issue at the github with very similar problem. The resolution is:

From discussion with team members, this is by design. The compiler's commitment is to provide a diagnostic, but exactly which diagnostic is a question that's reserved and we keep flexibility on that.

You have disabled one of the (at least) two warnings possible here, so you get this inconsistent behaviour. The same can be reproduced the other way around:

#pragma warning disable CS8509

// no warning 
static void F(Test? test) {
    var result = test switch
 {
     null => "Null",
     Test.Yes => "Yes",
     Test.No => "No",
 };
}

// warning 
static void F(Test? test) {
    var result = test switch
 {
     Test.Yes => "Yes",
     Test.No => "No",
     null => "Null",
 };
}

Demo @sharplab

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • Thanks for linking to this. Switching on Enum is my workaround for lacking the Discriminated Unions in C#. For this, CS8509 is much more valuable than CS8524 and I can not have both. So disabling 8524 is a common practice for anyone using C# as a functional language. Sad :( – Xiaoguo Ge May 25 '23 at 00:48
  • @XiaoguoGe I believe discriminated unions will finally come into C# (or at least hope, but they are investigated at least). Also you can look into utilizing something like [`OneOf`](https://github.com/mcintyre321/OneOf). In theory an analyzer can be written for it (if not already) which will check the exhaustive matching. – Guru Stron May 25 '23 at 00:53
  • 1
    I am using `OneOf` for ad-hoc types that form a union. But for related types, I am using inheritance with a `Kind` enum property and then switching on `Kind` enum. Exhaustiveness check(CS8509) on Enum is important in my use case. – Xiaoguo Ge May 25 '23 at 00:56