C# 8 switch expression with multiple cases with same result

前端 未结 4 1335
终归单人心
终归单人心 2020-12-05 12:46

How can a switch expression be written to support multiple cases returning the same result?

With C# prior to version 8, a switch may be written like so:



        
相关标签:
4条回答
  • 2020-12-05 13:09

    C# 9 supports the following:

    var switchValue = 3;
    var resultText = switchValue switch
    {
        1 or 2 or 3 => "one, two, or three",
        4 => "four",
        5 => "five",
        _ => "unknown",
    };
    

    Alternatively:

    var switchValue = 3;
    var resultText = switchValue switch
    {
        >= 1 and <= 3 => "one, two, or three",
        4 => "four",
        5 => "five",
        _ => "unknown",
    };
    

    Source


    For older versions of C#, I use the following extension method:

    public static bool In<T>(this T val, params T[] vals) => vals.Contains(val);
    

    like this:

    var switchValue = 3;
    var resultText = switchValue switch
    {
        var x when x.In(1, 2, 3) => "one, two, or three",
        4 => "four",
        5 => "five",
        _ => "unknown",
    };
    

    It's a little more concise than when x == 1 || x == 2 || x == 3 and has a more natural ordering than when new [] {1, 2, 3}.Contains(x).

    0 讨论(0)
  • 2020-12-05 13:09

    If your switch type is a flag enum

    [System.Flags]
    public enum Values 
    {
        One = 1, 
        Two = 2, 
        Three = 4,
        Four = 8,
        OneToThree = One | Two | Three
    }
    
    var resultText = switchValue switch
    {
        var x when Values.OneToThree.HasFlag(x) => "one to three",
        Values.Four => "4",
        _ => "unknown",
    };
    
    0 讨论(0)
  • 2020-12-05 13:12

    I got around to installing it, but I have not found a way to specify multiple, separate case labels for a single switch section with the new syntax.

    However, you can create a new variable that captures the value and then use a condition to represent the cases that should have the same result:

    var resultText = switchValue switch
    {
        var x when
            x == 1 ||
            x == 2 ||
            x == 3 => "one to three",
        4 => "four",
        5 => "five",
        _ => "unknown",
    };
    

    This is actually more concise if you have many cases to test, because you can test a range of values in one line:

    var resultText = switchValue switch
    {
        var x when x > 0 && x < 4 => "one to three",
        4 => "four",
        5 => "five",
        _ => "unknown",
    };
    
    0 讨论(0)
  • 2020-12-05 13:16

    Sadly, this appears to be a shortcoming in the switch-expression syntax, relative to the switch-statement syntax. As other posters have suggested, the rather clumsy var syntax is your only real option.

    So you might have been hoping you could write:

    switchValue switch {
        Type1 t1:
        Type2 t2:
        Type3 t3 => ResultA, // where the ResultX variables are placeholders for expressions.
        Type4 t4 => ResultB,
        Type5 t5 => ResultC
    };
    

    Instead you will need to write the rather awkward code below, with typename sprayed about:

    switchValue switch {
        var x when x is Type1 || x is Type2 || x is Type 3 => ResultA,
        Type4 t4 => ResultB,
        Type5 t5 => ResultC
    };
    

    In such a simple example, you can probably live with this awkwardness. But more complicated example are much less liveable with. In fact my examples are actually a simplification of an example drawn from our own code base, where I was hoping to convert a switch-statement, with roughly six outcomes but over a dozen type-cases, into a switch-expression. And the result was clearly less readable than the switch-statement.

    My view is that if the switch-expression needs shared outcomes and is more than a few lines long, then you are better off sticking to a switch-statement. Boo! It's more verbose but probably a kindness to your teammates.

    ResultType tmp;
    switch (switchValue) {
        case Type1 t1:
        case Type2 t2:
        case Type3 t3:
            tmp = ResultA;
            break;
        case Type4 t4:
            tmp = ResultB;
            break;
        case Type5 t5:
            tmp = ResultC;
            break;
    };
    return tmp;
    
    0 讨论(0)
提交回复
热议问题