157

如何编写 switch 表达式以支持返回相同结果的多种情况?

在版本 8 之前的 C# 中,可以这样编写开关:

var switchValue = 3;
var resultText = string.Empty;
switch (switchValue)
{
    case 1:
    case 2:
    case 3:
        resultText = "one to three";
        break;
    case 4:
        resultText = "four";
        break;
    case 5:
        resultText = "five";
        break;
    default:
        resultText = "unkown";
        break;
}

当我使用带有表达式语法的 C# 版本 8 时,就像这样:

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

所以我的问题是:如何将案例 1、2 和 3 变成一个 switch-case-arm,这样就不需要重复该值?

根据“ Rufus L ”的建议更新:

对于我给定的示例,这是有效的。

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

但这并不是我想要完成的。这仍然只是一种情况(带有过滤条件),而不是多种情况产生相同的右手结果。

4

6 回答 6

128

我开始安装它,但我还没有找到一种方法来使用新语法为单个 switch 部分指定多个单独的 case 标签。

但是,您可以创建一个新变量来捕获该值,然后使用条件来表示应该具有相同结果的情况:

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

如果您有很多案例要测试,这实际上更简洁,因为您可以在一行中测试一系列值:

var resultText = switchValue switch
{
    var x when x > 0 && x < 4 => "one to three",
    4 => "four",
    5 => "five",
    _ => "unknown",
};
于 2019-06-19T22:51:30.363 回答
120

C# 9 支持以下内容:

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

或者:

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

资源


对于旧版本的 C#,我使用以下扩展方法:

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

像这样:

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

它比 . 更简洁when x == 1 || x == 2 || x == 3,排序更自然when new [] {1, 2, 3}.Contains(x)

于 2020-05-13T12:03:55.207 回答
18

遗憾的是,相对于 switch-statement 语法,这似乎是 switch-expression 语法的一个缺点。正如其他海报所建议的那样,相当笨拙的var语法是您唯一真正的选择。

所以你可能一直希望你能写:

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

相反,您将需要编写下面相当笨拙的代码,并使用 typename 喷洒:

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

在这样一个简单的例子中,你可能可以忍受这种尴尬。但是更复杂的例子就不那么适合了。事实上,我的示例实际上是从我们自己的代码库中提取的示例的简化,我希望在其中将具有大约六个结果但十多个类型案例的 switch 语句转换为 switch 表达式。结果显然不如 switch 语句可读。

我的观点是,如果 switch 表达式需要共享结果并且长度超过几行,那么你最好坚持使用 switch 语句。嘘!它更冗长,但可能是对你的队友的善意。

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;
于 2019-10-20T07:27:29.780 回答
4

C#9 解决了这个多案例问题:

    var result = foo switch
    {
        1 => ...,
        2 or 3 => ...,
        _ => throw ...
    };
于 2022-01-28T16:26:36.240 回答
0

如果您的开关类型是标志枚举

[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",
};
于 2020-01-08T02:46:31.103 回答
0

如果您仍在使用 C# 8,因此无法使用上述答案中的 C# 9方法,您也可以以一种避免创建与接受的答案相同的值1 or 2 or 3 =>的额外变量的方式编写它(其中当然是完全正确的,我只是建议一个替代方案,因为我不喜欢那个额外的)。xswitchValuex

var list = new List<int> { 3, 4, 5 };

var resultText = switchValue switch
{
    1 => "one",
    2 => "two",
    _ when list.Contains(switchValue) => "three to five",
    _ => "unknown",
};

显然你可以_ when用任何东西替换后面的条件,比如switchValue == 3 || switchValue == 4 || switchValue == 5; 答案的重点是显示_ when位。

我只是想到了_ when =>“其他时候”和“其他时候”的_ =>意思。

于 2021-10-27T14:56:53.097 回答