(all code is here)
Overview of scenarios where you can use pattern matching. These techniques may improve the readability and correctness of your code.
Switch statement vs switch expression
First of all we need to clear when should we use which one
Use switch statement (old) when:
- you need to call
void methods
- you need to execute multiple tasks
- the result is not a value, but they’re actions
Use switch expression (new) when:
and the following void calls (they’re abstract just for the sake of the example as what they do is not important)
public abstract void UpdatePendingOrder(Order order);
public abstract void UpdateCancelledOrder(Order order);
public abstract void UpdateCompletedOrder(Order order);
Example on how to execute a call with secondary task
// DON'T DO THIS
public void NestedIfElseStatement(Order order)
{
if (order.Status == "Pending")
{
UpdatePendingOrder(order);
SendKpis(order);
}
else if (order.Status == "Completed")
{
UpdateCompletedOrder(order);
SendKpis(order);
}
else if (order.Status == "Cancelled")
{
UpdateCancelledOrder(order);
SendEmail(order);
}
else
{
throw new InvalidOperationException("Unknown status");
}
}
As this processes each status executing multiple tasks we’d solve this with a switch statement
public void SwitchStatement(Order order)
{
switch (order.Status)
{
case "Pending":
UpdatePendingOrder(order);
SendKpis(order);
break;
case "Completed":
UpdateCompletedOrder(order);
SendKpis(order);
break;
case "Cancelled":
UpdateCancelledOrder(order);
SendEmail(order);
break;
default:
throw new InvalidOperationException("Unknown status");
}
}
switch expression
We have the following record
public record Reference(int Id, bool Completed);
With the following methods
public abstract Reference GetPendingOrderRef(Order order);
public abstract Reference GetCancelledOrderRef(Order order);
public abstract Reference GetCompletedOrderRef(Order order);
Here we have a process where each status maps to exactly one execution and we have no secondary side effects.
// DON'T DO THIS
public Reference NestedIfElseExpression(Order order)
{
if (order.Status == "Pending")
{
return GetPendingOrderRef(order);
}
else if (order.Status == "Completed")
{
return GetCompletedOrderRef(order);
}
else if (order.Status == "Cancelled")
{
return GetCancelledOrderRef(order);
}
else
{
throw new InvalidOperationException("Unknown status");
}
}
this is the kind of case we may solve through switch expressions
public Reference SwitchExpression(Order order) =>
order.Status switch
{
"Pending" => GetPendingOrderRef(order),
"Completed" => GetCompletedOrderRef(order),
"Cancelled" => GetCancelledOrderRef(order),
_ => throw new InvalidOperationException("Unknown status"),
};
_ is the discard pattern that matches all values. It handles any error conditions where the value doesn’t match one of the defined values.
Read More