具有相同结果的多个情况的C#8开关表达式

具有相同结果的多个情况的C#8开关表达式,c#,c#-8.0,switch-expression,C#,C# 8.0,Switch Expression,如何编写开关表达式以支持返回相同结果的多个情况 对于版本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 =

如何编写开关表达式以支持返回相同结果的多个情况

对于版本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#version 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转换为一个开关箱臂,这样值就不需要重复了

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

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

var switchValue = 3;
var resultText = switchValue switch
{
    var x when (x >= 1 && x <= 3) => "one to three",
    4 => "four",
    5 => "five",
    _ => "unknown",
};
var开关值=3;
var resultText=开关值开关
{
变量x(x>=1&&x“一对三”,
4=>“四”,
5=>“五”,
_=>“未知”,
};

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

我开始安装它,但我还没有找到一种方法来使用新语法为单个开关节指定多个单独的情况标签

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

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",
};
var resultText=switchValue开关
{
当x>0时变量x&&x<4=>“一对三”,
4=>“四”,
5=>“五”,
_=>“未知”,
};

遗憾的是,与switch语句语法相比,这似乎是switch表达式语法的一个缺点。正如其他海报所建议的,相当笨拙的
var
语法是您唯一真正的选择

所以你可能希望你能写:

switchValue开关{
类型1 t1:
类型2 t2:
Type3 t3=>ResultA,//其中ResultX变量是表达式的占位符。
类型4 t4=>ResultB,
类型5 t5=>ResultC
};
相反,您将需要编写以下相当笨拙的代码,其中typename的内容如下:

switchValue开关{
当x是类型1时的变量x | | x是类型2 | | x是类型3=>ResultA,
类型4 t4=>ResultB,
类型5 t5=>ResultC
};
在这样一个简单的示例中,您可能会遇到这种尴尬。但更复杂的示例更不适合使用。事实上,我的示例实际上是从我们自己的代码库中提取的一个示例的简化,我希望将一个具有大约六种结果但有十几种类型的switch语句转换为switch expr结果显然不如switch语句可读

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

ResultType tmp;
开关(开关值){
病例类型1 t1:
病例类型2 t2:
案例类型3 t3:
tmp=结果;
打破
案例类型4 t4:
tmp=ResultB;
打破
案例类型5 t5:
tmp=结果;
打破
};
返回tmp;

如果开关类型是标志枚举

[系统标志]
公共枚举值
{
1=1,
二等于二,
三等于四,
四等于八,
一棵树=一|二|三棵树
}
var resultText=开关值开关
{
当值为.OneToThree.HasFlag(x)=>“一对三”时的变量x,
Values.Four=>“4”,
_=>“未知”,
};
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",
};

当x==1 | | x==2 | | x==3时,它比
更简洁,并且比新[]{1,2,3}.包含(x)时的
具有更自然的顺序

您想实现什么?Switch表达式不是Switch语句,fall-through是明确禁止的。
when
比fall-through功能强大得多。如果需要,您可以将
Contains
与值数组一起使用。当listOfValues.Contains(x)
并根据需要处理尽可能多的案例。我不想在这里忽略这些案例。如我问题的第一个代码块所示,案例1、2和3执行完全相同的右臂代码。为了解决这个问题,我在这里举了一个非常简单的例子。假设案例1、2、3将评估非常不同和复杂的内容ke模式与'when'等匹配。第一个代码块通过cases。这就是
case 1:case 2:
do-它们是空块通过case进入下一个case。fall-through我的意思是case上没有空体。fall-through是明确禁止的。
when
子句比fal强大得多当listOfValues.Contains(x)时,您可以使用单个
var x,而不是编写3或10个
case
语句
@PanagiotisKanavos我刚刚了解到,虽然禁止跳转,但这不是跳转。这是多重匹配,允许使用wich并编译:@PanagiotisKanavos,除非它不是跳转,这是我的观点。“switch语句中只有一个switch段执行。C#不允许从一个switch段继续执行到下一个switch段。因此,以下代码生成一个编译器错误CS0163:“控制不能从一个case标签()掉到另一个。”"-|这是由多个标签进行的多重匹配。而不是像Python中那样的逗号分隔列表。@PanagiotisKanavos可能会让您感到困惑的是,许多Langauge通过Fall-Through实现了多重匹配。但在C中,它们与委托和整数或接口和类一样不同。@RufusL我不确定正确的方法是什么我甚至知道,这不是一个失败。我实际上是在想我自己,就像我在早期的C++时代里通过FaltHHOHE记忆的那样。但是纠正我的人是对的:它不是失败的。它可以。
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",
};