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 an expression_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.

Thanks to l33t’s comment. He pointed out that using such approach would cause each case expression suffer from very costly delegate allocation (verified in .NET 5). So it is one more reason not to use this approach and prefer to use switch-case or if-else.


May be in future version of C# this limitation will be relaxed (see this link):

The switch_expression is not permitted as an expression_statement.

We are looking at relaxing this in a future revision.

But I haven’t found an appropriate proposal in csharplang repo.

Leave a Comment