TL;DR
这是不可能的。在C# 8 switch expression 不能返回void。它必须返回一个值,并且必须使用该值(分配给变量,作为参数传递给方法,作为方法的结果返回等)。但是有一个解决方法。我们可以编写一个switch expression,它返回一个delegate(例如Action 类型),然后立即调用它:
(stringValue switch
{
"Add" => (Action) Add,
"Subtract" => Subtract,
_ => throw new ArgumentOutOfRangeException()
})();
这种方法也可以用于expression bodied methods。这里是demo。
说明
这可能吗?
在C# 8 这是不可能的。 C# specification 中描述了此限制。
让我们参考C# specification。从页面Recursive Pattern Matching - Switch Expression 和Statements 我们可以了解到:
-
switch_expression 不允许作为expression_statement。
-
expression_statement 计算给定的表达式。表达式计算的值(如果有)将被丢弃。
从这两条语句我们可以得出结论,switch_expression 不能在expression_statement 的上下文中使用,其结果值不能被丢弃。必须使用结果值,例如,它必须分配给变量、作为参数传递给方法或作为方法的结果返回。因此编译器抱怨switch expression 不能用作语句。
如果我们只需要打开一个字符串值并执行一个方法
什么都不返回(没有返回类型/void),我们该怎么做呢?我是
正在考虑某种形式的 Func,但不确定确切的语法。
我们可以使用下一种方法:编写一个switch expression,它返回一个delegate,然后立即调用它。例如:
(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()
})();
这里是complete sample。
在我看来,这种解决方法看起来很丑陋,我个人更喜欢使用 switch-case 或 if-else 而不是这种结构。
感谢l33t的评论。他指出,使用这种方法会导致每个case expression遭受非常昂贵的delegate allocation(在.NET 5中验证)。所以还有一个理由不使用这种方法,而是更喜欢使用switch-case 或if-else。
可能会在C#的未来版本中放宽此限制(see this link):
switch_expression 不允许作为expression_statement。
我们正在考虑在未来的修订中放宽这一点。
但是我在csharplang repo没有找到合适的提案。