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-case
or是另一个原因if-else
。
可能在以后的版本中C#
这个限制会放宽(见这个链接):
switch_expression
不允许expression_statement
作为.
我们正在考虑在未来的修订中放宽这一点。
但我没有在csharplang repo
.