void 方法的 C# 8 switch 表达式
C# 8 switch expression for void methods
我知道 C# 8
switch expression
语法用于 return 一个值或 属性 匹配的方法。但是,如果我们只需要打开一个字符串值并执行一个 return 什么都没有的方法(没有 return type/void),那么我们如何去做呢?我在想某种形式的 Func 但不确定确切的语法。我知道我们可以用常规的 case 语句以旧的方式做到这一点,但我想看看我们是否可以用更新的语法实现同样的效果。
这是问题的例子
switch (stringvalue)
{
case "Add": Add(); break;
case "Subtract": Subtract(); break;
}
可能是这样的:
stringvalue switch
{
"Add" => Add(),
"Subtract" => Subtract()
}
// but this complains that there needs to be assignment on left side for this
这可能吗?
TL;DR
不可能在C# 8
switch expression
不能returnvoid
.它必须 return 一个值并且必须使用该值(分配给变量,作为参数传递给方法,return 作为方法的结果等)。但是有一个解决方法。我们可以写一个 switch expression
,return 是一个 delegate
(例如 Action
类型),然后立即调用它:
(stringValue switch
{
"Add" => (Action) Add,
"Subtract" => Subtract,
_ => throw new ArgumentOutOfRangeException()
})();
这种方法也可以与 expression bodied methods
一起使用。这里是 demo.
说明
Is this possible?
在C# 8
中是不可能的。 C# specification
.
中描述了此限制
参考C# specification
。从第 Recursive Pattern Matching - Switch Expression
and Statements
页我们可以了解到:
-
The switch_expression
is not permitted as an expression_statement
.
-
An expression_statement
evaluates a given expression. The value computed by the expression, if any, is discarded.
从这两条语句可以得出,switch_expression
不能用在expression_statement
的上下文中,其结果值不能 ]被丢弃。必须使用结果值,例如,必须将其分配给变量、作为参数传递给方法或作为方法的结果 returned。因此编译器抱怨说 switch expression
不能用作语句。
if we just need to switch on a string value and execute a method that
returns nothing (no return type/void), how do we go about it? I am
thinking some form of Func but not sure of the exact syntax.
我们可以使用下一个方法:写一个switch expression
,return是一个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):
The switch_expression
is not permitted as an expression_statement
.
We are looking at relaxing this in a future revision.
但是我在csharplang repo
中没有找到合适的方案。
正如 Iliar 告诉你的那样,这是不可能的。我有时使用的解决方法是添加一个始终 returns true 的本地函数,并且我在 switch 分配中使用了一个丢弃字符。我发现此解决方法比使用委托的方法更清晰。
例如,您可以在切换之前将此添加到您的代码中:
bool Add() { [HEREYOURCODEToAdd]; return true;}
bool Substract() { [HEREYOURCODETOSubstract]; return true;}
然后你会这样称呼它:
_ = stringvalue switch {
"Add" => Add(),
"Substract" => Substract(),
};
我认为这种方法有一些用例。例如,如果你想在开关中使用元组模式,它会比许多废弃的 if 更具可读性。这是我正在使用的代码,我认为这种方法比 ifs:
bool agregar(int índiceInicial, int índiceFinal) { visitasJson.Add(json[índiceInicial..índiceFinal]); return true; };
_ = (índiceInicial, índiceFinal) switch {
(0, -1) => agregar(índiceInicial + 1, índiceFinal - 3),
(_, -1) => agregar(índiceInicial, índiceFinal - 1),
(0, _) => agregar(índiceInicial + 5, índiceFinal),
(_, _) => agregar(índiceInicial, índiceFinal),
};
你真的想在你的用例中使用 switch 表达式吗,传统的方式要好得多。
所有建议的解决方案,如委托、丢弃都是解决方法。
您试图错误地使用 switch 表达式。
我知道 C# 8
switch expression
语法用于 return 一个值或 属性 匹配的方法。但是,如果我们只需要打开一个字符串值并执行一个 return 什么都没有的方法(没有 return type/void),那么我们如何去做呢?我在想某种形式的 Func 但不确定确切的语法。我知道我们可以用常规的 case 语句以旧的方式做到这一点,但我想看看我们是否可以用更新的语法实现同样的效果。
这是问题的例子
switch (stringvalue)
{
case "Add": Add(); break;
case "Subtract": Subtract(); break;
}
可能是这样的:
stringvalue switch
{
"Add" => Add(),
"Subtract" => Subtract()
}
// but this complains that there needs to be assignment on left side for this
这可能吗?
TL;DR
不可能在C# 8
switch expression
不能returnvoid
.它必须 return 一个值并且必须使用该值(分配给变量,作为参数传递给方法,return 作为方法的结果等)。但是有一个解决方法。我们可以写一个 switch expression
,return 是一个 delegate
(例如 Action
类型),然后立即调用它:
(stringValue switch
{
"Add" => (Action) Add,
"Subtract" => Subtract,
_ => throw new ArgumentOutOfRangeException()
})();
这种方法也可以与 expression bodied methods
一起使用。这里是 demo.
说明
Is this possible?
在C# 8
中是不可能的。 C# specification
.
参考C# specification
。从第 Recursive Pattern Matching - Switch Expression
and Statements
页我们可以了解到:
-
The
switch_expression
is not permitted as anexpression_statement
. -
An
expression_statement
evaluates a given expression. The value computed by the expression, if any, is discarded.
从这两条语句可以得出,switch_expression
不能用在expression_statement
的上下文中,其结果值不能 ]被丢弃。必须使用结果值,例如,必须将其分配给变量、作为参数传递给方法或作为方法的结果 returned。因此编译器抱怨说 switch expression
不能用作语句。
if we just need to switch on a string value and execute a method that returns nothing (no return type/void), how do we go about it? I am thinking some form of Func but not sure of the exact syntax.
我们可以使用下一个方法:写一个switch expression
,return是一个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):
The
switch_expression
is not permitted as anexpression_statement
.We are looking at relaxing this in a future revision.
但是我在csharplang repo
中没有找到合适的方案。
正如 Iliar 告诉你的那样,这是不可能的。我有时使用的解决方法是添加一个始终 returns true 的本地函数,并且我在 switch 分配中使用了一个丢弃字符。我发现此解决方法比使用委托的方法更清晰。
例如,您可以在切换之前将此添加到您的代码中:
bool Add() { [HEREYOURCODEToAdd]; return true;}
bool Substract() { [HEREYOURCODETOSubstract]; return true;}
然后你会这样称呼它:
_ = stringvalue switch {
"Add" => Add(),
"Substract" => Substract(),
};
我认为这种方法有一些用例。例如,如果你想在开关中使用元组模式,它会比许多废弃的 if 更具可读性。这是我正在使用的代码,我认为这种方法比 ifs:
bool agregar(int índiceInicial, int índiceFinal) { visitasJson.Add(json[índiceInicial..índiceFinal]); return true; };
_ = (índiceInicial, índiceFinal) switch {
(0, -1) => agregar(índiceInicial + 1, índiceFinal - 3),
(_, -1) => agregar(índiceInicial, índiceFinal - 1),
(0, _) => agregar(índiceInicial + 5, índiceFinal),
(_, _) => agregar(índiceInicial, índiceFinal),
};
你真的想在你的用例中使用 switch 表达式吗,传统的方式要好得多。
所有建议的解决方案,如委托、丢弃都是解决方法。
您试图错误地使用 switch 表达式。