S2589: Strange interaction with enums and switch expressions

  • What language is this for?
    C# (.NET 7)
  • Which rule?
    S2589
  • Are you using
    SonarLint 7.3.0.77872 on Visual Studio 2022 17.4.4 (not connected)

I noticed a case of a switch expression not getting correctly interpreted when using an enum.
Consider the following minimal reproduction:

using System;

namespace Test;

public enum UserType
{
    Internal,
    External,
    Other
}

public interface IUser
{
    int Id { get; }
    string LoginName { get; }
    UserType UserType { get; }
}

public static class Program
{
    public static void Check_SwitchExpression(IUser user)
    {
        if (user.UserType switch
        {
            UserType.Internal => user.Id == 1,
            UserType.External => user.LoginName == "test",
            _ => false,
        })
            return;

        throw new ApplicationException("not authorized");
    }

    public static void Check_SwitchStatement(IUser user)
    {
        switch (user.UserType)
        {
            case UserType.Internal:
                if (user.Id == 1) return;
                break;
            case UserType.External:
                if (user.LoginName == "test") return;
                else break;
        }
        throw new ApplicationException("not authorized");
    }

    public static void Main()
    {
        // ignore this
    }
}

The method Check_SwitchExpression raises the following report:

S2589: Change this condition so that it does not always evaluate to ‘False’

Note that changing the final default branch to true makes the rule say the opposite.
Unless I am missing something, the two Check methods should be logically equivalent.

For further reference here is a decompiled version of the code:

// Decompiled with JetBrains decompiler
// Type: Test.Program
// Assembly: MiscTests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

using System;

namespace Test
{
  public static class Program
  {
    public static void Check_SwitchExpression(IUser user)
    {
      UserType userType = user.UserType;
      if (true)
        ;
      bool flag;
      switch (userType)
      {
        case UserType.Internal:
          flag = user.Id == 1;
          break;
        case UserType.External:
          flag = user.LoginName == "test";
          break;
        default:
          flag = false;
          break;
      }
      if (true)
        ;
      if (!flag)
        throw new ApplicationException("not authorized");
    }

    public static void Check_SwitchStatement(IUser user)
    {
      switch (user.UserType)
      {
        case UserType.Internal:
          if (user.Id == 1)
            return;
          break;
        case UserType.External:
          if (user.LoginName == "test")
            return;
          break;
      }
      throw new ApplicationException("not authorized");
    }

    public static void Main()
    {
    }
  }
}

Hello @m-gallesio and thank you for the report.
I confirm this is as an FP and have created an issue in our backlog:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.