0

Here's the code that I have now:

        return cardChoice switch
        {
            var x when
                x == CC.F1 ||
                x == CC.F2 ||
                x == CC.F3 ||
                x == CC.F4 ||
                x == CC.F5 => $"There are 0 cards in this collection.Add cards by tapping > of any card set then choose {cardChoice}.",
                CC.H       => "There are 0 cards in this collection. Add cards by tapping > of any card set then choose Hide.",
            _ => throw new InvalidEnumArgumentException("Unhandled value: " + cardChoice.ToString()),
        };

Is there a way the checking with x == .. could be further simplified?

Samantha J T Star
  • 30,952
  • 84
  • 245
  • 427

2 Answers2

2

Unfortunately, switch expressions can currently only match a single pattern. There's a feature request for composite patterns, but nothing more than that right now. It's one of the few areas where using a switch statement with multiple case labels can end up being simpler than using a switch expression. (And you might want to consider that option, if CC.F1 etc are constants that can be used in case labels.)

In your example code I'd probably just use a conditional operator instead, but I assume your real switch expression has other cases to consider.

In terms of avoiding having five comparisons, you could create a collection of some kind and just use var x when FCollection.Contains(x) as your guarded pattern.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

You could also consider dropping enum and switch entirely, and use an Enumeration class instead.

This way you code will end up as:

public CardType : Enumeration
{
    public CardType( int id, string name, bool chooseCard )
      : base(id,name)
    {
      ChooseCard = chooseCard;
    }

    public static readonly Unknown = new CardType(-1,"unknown", false);
    public static readonly F1 = new CardType(1,"F1", true);
    public static readonly F2 = new CardType(2,"F2", true);
    public static readonly F3 = new CardType(3,"F3", true);
    public static readonly F4 = new CardType(4,"F4", true);
    public static readonly F5 = new CardType(5,"F5", true);
    public static readonly H = new CardType(10,"H", false);

    public bool ChooseCard { get; }
    public bool ChooseHide => ChooseCard == false;
    public bool IsUnknown => Id == Unknown.Id;
}

TestChoice( CardType cardChoice ) {
  if( cardChoice.IsUnknown )
     throw new InvalidEnumArgumentException("Unhandled value: " + cardChoice.ToString());  
  if( cardChoice.ChooseCard )
    return $"There are 0 cards in this collection.Add cards by tapping > of any card set then choose {cardChoice}.";
  if( cardChoice.ChooseHide )
    return "There are 0 cards in this collection. Add cards by tapping > of any card set then choose Hide.";
 ...
}

example written with free hands, no compiling

You can specialized each card by its own type, if more properties are added.

It requires a little more coding when declaring the "enum", but simplifies where ever it is used - makes the code more readable and understandable.

Read more here: https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/enumeration-classes-over-enum-types

Frank Nielsen
  • 1,546
  • 1
  • 10
  • 17