One of new features introduced by C# 7.0 is support for pattern matching in switch statements. It’s like mix of switch and if statements so we don’t have to nest these two. This blog post introduces pattern matching in switch statements and shows what C# compiler produces of switch statements.
Let’s take a look at the following switch statement that introduces new concepts.
public static void Show(Shape shape)
{
switch (shape)
{
case Circle c:
Console.WriteLine($"circle with radius {c.Radius}");
break;
case Rectangle s when (s.Length == s.Height):
Console.WriteLine($"{s.Length} x {s.Height} square");
break;
case Rectangle r:
Console.WriteLine($"{r.Length} x {r.Height} rectangle");
break;
default:
Console.WriteLine("unknown shape");
break;
case null:
Console.WriteLine("shape is null");
break;
}
}
One new thing is here when keyword. Using when keyword we can specify constraints to case statements. The code above has two rules for Rectangle. First of them is applyed when height and length are equal meaning that it’s a square. If shape is Rectangle then first condition for rectangles that holds true is taken. If rectangle isn’t square then second rule is applied. Based on this we can make important conclusion: order of case statements is important when applying multiple rules to same case.
Default case is applied when all other cases are tried and no matching one is found. When shape is null in the code above then case for null is applied although it’ is after default. Default case is applied when we use Octahedron shape.
SwitchPatternsSample.Show(null);
// output: shape is null
SwitchPatternsSample.Show(new Octahedron());
// output: unknown shape
Now we have clear idea how pattern matching works with switch statements and it’s time to see what compiler produces of code above.
Switch with pattern matching after compiler
Let’s make release build of sample code, remove pdb-file from output directory and open DLL-file using JetBrains dotPeek to see what compiler produced. As we can see our good looking switch is turned to controlled chaos of if statements.
public static void Show(Shape shape)
{
Shape shape1 = shape;
if (shape1 != null)
{
Circle circle;
if ((circle = shape1 as Circle) == null)
{
Rectangle rectangle1;
if ((rectangle1 = shape1 as Rectangle) != null)
{
Rectangle rectangle2 = rectangle1;
if (rectangle2.Length == rectangle2.Height)
{
Console.WriteLine(string.Format("{0} x {1} square", (object)rectangle2.Length, (object)rectangle2.Height));
}
else
{
Rectangle rectangle3 = rectangle1;
Console.WriteLine(string.Format("{0} x {1} rectangle", (object)rectangle3.Length, (object)rectangle3.Height));
}
}
else
Console.WriteLine("unknown shape");
}
else
Console.WriteLine(string.Format("circle with radius {0}", (object)circle.Radius));
}
else
Console.WriteLine("shape is null");
}
Take a minute to look at this code. We had nice and readable switch statement and this is what we actually got.
Wrapping up
Pattern matching in C# 7.0 is good new feature as we can use it for writing cleaner code. We have to keep in mind that order of case statements is important. If there are more than one rule for type of case then first one in the list is taken. Due to nature of pattern matching switch statements, default clause is always evaluated last. We can write more case statements after default and they are still evaluated.
View Comments (0)