TL;博士
这不可能。在C# 8 switch expression无法返回void。它必须返回一个值,并且必须使用该值(分配给变量,作为参数传递给方法,作为方法的结果返回等)。但是有一个解决方法。我们可以编写一个switch expression返回 adelegate(Action例如,类型为 )然后立即调用它的 a:
(stringValue switch
{
"Add" => (Action) Add,
"Subtract" => Subtract,
_ => throw new ArgumentOutOfRangeException()
})();
这种方法也可以与expression bodied methods. 这是演示。
解释
这可能吗?
在C# 8它是不可能的。此限制在 中进行了描述C# specification。
让我们参考C# specification。从页面中Recursive Pattern Matching - Switch Expression,Statements我们可以了解到:
-
switch_expression不允许expression_statement作为.
-
Anexpression_statement计算给定的表达式。表达式计算的值(如果有)将被丢弃。
从这两个陈述我们可以得出结论,switch_expression不能在 的上下文中使用expression_statement,并且它的结果值不能被丢弃。必须使用结果值,例如,它必须分配给变量、作为参数传递给方法或作为方法的结果返回。因此编译器抱怨switch expression不能用作语句。
如果我们只需要打开一个字符串值并执行一个什么都不返回的方法(没有返回类型/void),我们该怎么做呢?我正在考虑某种形式的 Func 但不确定确切的语法。
我们可以使用下一种方法:编写一个switch expression返回 adelegate然后立即调用它的 a。例如:
(stringValue switch
{
"Add" => (Action) Add,
"Subtract" => Subtract,
_ => throw new ArgumentOutOfRangeException()
})();
这种方法也可以用来声明expression bodied members:
private static void Demo(string str) =>
(str switch
{
"Add" => (Action) Add,
"Subtract" => Subtract,
_ => throw new ArgumentOutOfRangeException()
})();
这是完整的示例。
在我看来,这种解决方法看起来很难看,我个人更愿意使用switch-case或if-else代替这种结构。
感谢 l33t 的评论。他指出,使用这种方法会导致每个人都case expression遭受非常昂贵的委托分配(在 中验证.NET 5)。因此,不使用这种方法并更喜欢使用switch-caseor是另一个原因if-else。
可能在以后的版本中C#这个限制会放宽(见这个链接):
switch_expression不允许expression_statement作为.
我们正在考虑在未来的修订中放宽这一点。
但我没有在csharplang repo.