Normally in our code it's necessary to evaluate the value of a variable or an expression to make a decision relative to the result obtained, typically do you need to evaluate if the value meets with a certain condition or pattern.
Maybe, you normally perform comparison or evaluation in your “if” statement, a “switch” statement, or a switch expression.
C#, like other programming languages, is evolving version by version and introduces new concepts that can help us to do a better code.
Since C# version 7.0 you can use pattern matching, and nowadays there are more than 7 types of pattern.
This will be a full review of all of them, and we will be explored in details in several chapters.
The chapter of today is Declaration Pattern.
let's begin
The Declaration Pattern
Available since C# 7.0, it is used to validate the type of an expression and if a match is ok set the result of expression in a variable.
Looks the following example. On this we use the declaration pattern to evaluate if the paramaters are able to be divisble. The parameters have been declared has “int?” so the values coud be “null” or a “number”.
- First we evaluate wether the value of “a parameter” is an int, if the number is null the result of the expression “a is int” will be false. By other hand wether is a number, then the value of “a” is set to variable “number”,
- Then we use the same logic to the parameter “b”, but setting the value to the “div” variable.
- And finally in the same expression we use the variable created on the step 2 (div variable) to validate if the value is greater than zero.
- To finally perform a standard division between two numbers.
Validating Type on runtime
Let's see another example now.
In the next example we will validate the type of an object using the declaration pattern.
We are asked to create a simple solution to add an additional tax only to liquor products from a store.
So we declare:
- IProduct Interface : On this interface we will define the sigin of the method to get total price from any product.
- BaseProduct class: This class implements the interface IProduct, and is an abstract class, and will be the super class for all derived kinds of products. On this class we declare the properties Name and BasePrice and define the standard code to the method getTotalPrice, that will be defined virtual, so any derived class can redefine its behavior.
- BaseProductWithTax: This class inherited from BaseProduct, and will be the super class from all the product who has a tax. on this class will add the Tax propertie, and override the method GetTotalPrice to add the tax.
- Electronic class: derived class from BaseProduct (concrete type of product) -** Liqueur class**: derived class from baseProductWhitTax. (specific type of a product with tax)
Now we will declare a list of different types of products and will be apply the tax only to objects if they derived only the Liquer class
How you can see on the line "if (product is BaseProduct baseProduct)"
of the method ShwoListOfProducts() this will be true for all instance of any class derived from BaseProduct, (electronic and liquier products, it's for all), and later in the line “if (product is BaseProductWithTax productWithTax)”
will be true only with the product of the type liquier, because this products inheritance from BaseProductWithTax class.
I hope this simple example can be usefull, on the next chapters will review other types of pattern matching, See you!
Top comments (3)
Nice example showing the pattern.
But this „Tax-Problem“ should be solved differently.
Tax should be an abstract property implemented in derived classes with either a constant value for it’s tax or some way to derermine „this’ own tax“. But it should be part of the class and should NOT come from outside.
I know pattern matching is coming from functional programming. But C# can use both paradigms and this is better solved with OOP.
Nevertheless good showing on how the pattern works. 👍
Hi Andreas, you are totally right about how this kind of problem must be solved. But my focus on this code is to show how the pattern works, and my intention was try to used an example more close to the reality. Anyway your comment help me to be more carefull with the examples, i take the challenge, thanks for your time and your comment.
„Must“ is pretty hard. But this problem and the class hierarchy are calling for another approach.
But „hey“: if it works, you are right.