Evolution of Pattern Matching up until C# 8.0
What is pattern matching ? Lets say that you have a simple hierarchy of shapes
Now if i make an assignment to a Shape
variable . I can assign either a rectangle or a circle. Here i will go with the rectangle
Shape shape = new Rectangle { Width = 100, Height = 100, };
How can you find out during runtime what kind of shape did i put in ?
This is the underling problem that pattern matching wants to solve. We will see how C# 8.0 finally came closer to a functional way of dealing with this problem.
Here we are going to see different ways of how to get a different description based on the shape type.
1.Using the Is keyword
We can go with something really basic using if statements :
2. Using the switch statement
Since C# 7.0 we can use the switch statement to separate the sub-types:
3. Use polymorphism
Yes by using polymorphism we can separate which Shape
type the variable was assigned, by invoking a polymorphic method:
now all the cases moved inside each class.
var description = shape.GetShapeDescription();
4.We can use Custom Pattern matching
Now we will refactor the previous case of polymorphism in order to abstract the mechanics of Polymorphism !!
we have this MatchWith method that we can use to separate the cases
public abstract T MatchWith<T>(
Func<Rectangle, T> rectangleCase,
Func<Circle, T> circleCase);
we are going to use it like this :
you can see that this is the same as the switch statement :
string GetShapeDescription(Shape shape)
{
switch (shape)
{
case Circle c:
return $"found a circle with radius {c.Radius}";
case Rectangle s:
return $"Found {s.Height }x {s.Width} rectangle";
default:
throw new System.Exception(nameof(shape));
}
};
Now the last step of the evolution
5.Using the C# 8.0 pattern matching
We can finally pattern match without the previous custom implementation using another syntax of the switch keyword :
it takes some time to get used to the syntax but it is easy to grasp. As you can see you can access the public Properties of the sub classes :
shape switch
{
Rectangle { Height: var h, Width: var w }
=> $"Found {h }x {w} rectangle",
Circle { Radius: var r }
=> $"found a circle with radius {r}",
}
one more example.Lets say we want to scale the shape we can write this function as an extension utilizing pattern matching
and use it like this :
var t1 = shape.Scale(x => x*x);
In Conclusion :
C# pattern matching finally brings another functional feature that will help C# developers write functional code more naturally.