C# 8 switch expression for void methods
TL;DR
It is not possible. In C# 8
switch expression
cannot return void
. It must return a value and this value must be consumed (assigned to a variable, passed as an argument to a method, returned as a result of a method, etc.). But there is a workaround. We can write a switch expression
that returns a delegate
(of type Action
, for example) and then immediately invokes it:
(stringValue switch
{
"Add" => (Action) Add,
"Subtract" => Subtract,
_ => throw new ArgumentOutOfRangeException()
})();
Such approach also can be used with expression bodied methods
. Here is demo.
Explanation
Is this possible?
In C# 8
it is not possible. This limitation is described in C# specification
.
Lets refer to C# specification
. From pages Recursive Pattern Matching - Switch Expression
and Statements
we can learn that:
-
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.
From these two statements we can conclude that switch_expression
cannot be used in the context of expression_statement
, and its result value cannot be discarded. The result value must be used, for example, it must be assigned to a variable, passed to a method as an argument or returned as a result of a method. Therefore compiler complains that switch expression
cannot be used as a statement.
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.
We can use the next approach: write a switch expression
that returns a delegate
and then immediately invokes it. For example:
(stringValue switch
{
"Add" => (Action) Add,
"Subtract" => Subtract,
_ => throw new ArgumentOutOfRangeException()
})();
This approarch also can be used to declare expression bodied members
:
private static void Demo(string str) =>
(str switch
{
"Add" => (Action) Add,
"Subtract" => Subtract,
_ => throw new ArgumentOutOfRangeException()
})();
Here is complete sample.
In my opinion such workaround looks ugly and personally I would prefer to use switch-case
or if-else
instead of such construction.
May be in future version of C#
this limitation will be relaxed (see this link):
The
switch_expression
is not permitted as anexpression_statement
.We are looking at relaxing this in a future revision.
But I haven't found an appropriate proposal in csharplang repo
.