Pattern Matching
Pattern Matching
Matching a Pattern
Introduction
As we saw in the previous lessons, C# makes extensive use of the switch statement. Besides the way the switch keyword is used like the if...else conditional statements, C# adds some extended functionalities referred to as pattern matching (you can see some of those functionalities in languages like F#).
Introduction to Switch Expressions
Consider the following function:
@page
@model PracticalLearning.Pages.Shared.RoadTrafficModel
@{
int period = GetPayrollFrequency();
double gs = GetGrossSalary();
double incomeTax = EvaluateIncomeTax(period, gs);
string strGrossSalary = $"{gs:f}";
string strIncomeTax = $"{incomeTax:f}";
}
@functions{
int GetPayrollFrequency()
{
int time;
/* Frequency by which the payroll is processed:");
* 1 - Weekly
* 2 - Biweekly
* 3 - Semimonthly
* 4 - Monthly */
time = 1;
return time;
}
double GetGrossSalary()
{
double sal = 1749.88;
return sal;
}
double EvaluateIncomeTax(int frequency, double sal)
{
double incomeTax = 0.00;
switch (frequency)
{
case 1:
incomeTax = 271.08 + (sal * 24 / 100);
break;
case 2:
incomeTax = 541.82 + (sal * 24 / 100);
break;
case 3:
incomeTax = 587.12 + (sal * 24 / 100);
break;
case 4:
incomeTax = 1174.12 + (sal * 24 / 100);
break;
}
return incomeTax;
}
}
<pre>Payroll Evaluation
------------------------
Gross Salary: @strGrossSalary
Income Tax: @strIncomeTax
========================</pre>
In the body of the function, we declared a local variable to hold the value to return from the function. If the function is a simple one, in the previous lesson, we saw that you don't need such a local variable. You can directly return the conditional value from each case. Here is an example:
@functions{ double EvaluateIncomeTax(int frequency, double sal) { switch (frequency) { case 1: return 271.08 + (sal * 24 / 100); case 2: return 541.82 + (sal * 24 / 100); case 3: return 587.12 + (sal * 24 / 100); case 4: return 1174.12 + (sal * 24 / 100); } } }
Instead of creating individual cases in a switch statement, you can use the => operator. To proceed, instead of a switch(expression) keyword with parentheses, replace it with the following formula:
return expression switch
Start the section with the return and the switch keywords without parentheses. Between those keywords, type the same type of expression we have used so far in the parentheses of switch, such as a variable. Follow the line with a body delimited by curly brackets as seen so far with any switch statement. In that body, create a section for each possible case. This time, instead of the case keyword followed by a colon, use the => operator. On the right side the => operator, write the expression that the case clause is supposed to return. End the expression with a comma and proceed with the next case. After the closing curly bracket, you must end the whole statement with a semicolon. Here is an example:
@page
@model PracticalLearning.Pages.Shared.RoadTrafficModel
@{
int period = 2;
double gs = 2268.93;
double incomeTax = EvaluateIncomeTax(period, gs);
string strGrossSalary = $"{gs:f}";
string strIncomeTax = $"{incomeTax:f}";
}
@functions{
double EvaluateIncomeTax(int frequency, double sal)
{
return frequency switch
{
1 => 271.08 + (sal * 24 / 100),
2 => 541.82 + (sal * 24 / 100),
3 => 587.12 + (sal * 24 / 100),
4 => 1174.12 + (sal * 24 / 100),
};
}
}
<pre>Payroll Evaluation
------------------------
Gross Salary: @strGrossSalary
Income Tax: @strIncomeTax
========================</pre>
This would produce:
Payroll Evaluation ------------------------ Gross Salary: 2268.93 Income Tax: 1086.36 ========================
The Default Case of a Switch Expression
As seen in the previous lesson, a typical switch statement can lead to a situation that doesn't fit any of the addressed cases, in which case you should have a default clause. If you are creating a switch expression, to create a default clause, use the underscore operator. Here is an example:
@page
@model PracticalLearning.Pages.Shared.RoadTrafficModel
@{
int time = 1;
int roadCategory = 1;
string strPeriod = IdentifyPeriodOfDay(time);
string strRoadCategory = IdentifyRoadType(roadCategory);
}
@functions{
/* Periods
* 1 - Monday-Friday - Night (7PM - 6AM)
* 2 - Monday-Friday - Morning Rush Hour (6AM - 9AM)
* 3 - Monday-Friday - Regular Time (9AM - 3PM)
* 4 - Monday-Friday - Afternoon Rush Hour (3PM - 7PM)
* 5 - Weekend (Saturday-Sunday) and Holidays */
string IdentifyPeriodOfDay(int period)
{
switch (period)
{
case 1:
return "Monday-Friday - Night (7PM - 6AM)";
case 2:
return "Monday-Friday - Morning Rush Hour (6AM - 9AM)";
default: // case 3:
return "Monday-Friday - Regular Time (9AM - 3PM)";
case 4:
return "Monday-Friday - Afternoon Rush Hour (3PM - 7PM)";
case 5:
return "Weekend (Saturday-Sunday) and Holidays";
}
}
/* Type of Road
* 1 - Interstate (Ex. I95)
* 2 - Federal/State Highway (Ex. US50)
* 3 - State Road (Ex. TN22, MD410)
* 4 - County/Local Road (Ex. Randolph Rd, Eusebio Ave, Abena Blvd) or Local - Unknown (Ex. Sterling Str, Garvey Court) */
string IdentifyRoadType(int type)
{
return type switch
{
1 => "Interstate",
2 => "Federal/State Highway",
3 => "State Road",
_ => "County/Local Road, Others"
};
}
}
<pre>Traffic Tickets System
----------------------------------------------------------
Road Category: @strRoadCategory
Time of Day: @strPeriod
==========================================================</pre>
Simplifying a Switch Expression
In our introduction to functions, we saw that, when a function returns a value, you can simplify its body by using the => operator. This functionality is also available for a switch expression. To apply it, after the parentheses of the function, remove the curly brackets of the function, replace the return keyword by the => operator, create the whole switch section, and end the whole statement with a semicolon. Here i5 an example:
@page
@model PracticalLearning.Pages.Shared.RoadTrafficModel
@{
int period = GetPayrollFrequency();
double gs = GetGrossSalary();
double incomeTax = EvaluateIncomeTax(period, gs);
string strGrossSalary = $"{gs:f}";
string strIncomeTax = $"{incomeTax:f}";
}
@functions{
int GetPayrollFrequency()
{
int time;
/* Frequency by which the payroll is processed:");
* 1 - Weekly
* 2 - Biweekly
* 3 - Semimonthly
* 4 - Monthly */
time = 3;
return time;
}
double GetGrossSalary()
{
double sal = 1884.68;
return sal;
}
double EvaluateIncomeTax(int frequency, double sal) =>
frequency switch
{
1 => 271.08 + (sal * 24 / 100),
2 => 541.82 + (sal * 24 / 100),
3 => 587.12 + (sal * 24 / 100),
4 => 1174.12 + (sal * 24 / 100),
_ => 0.00
};
}
<pre>Payroll Evaluation
--------------------------------
Payroll Frequency: Semimonthly
Gross Salary: @strGrossSalary
Income Tax: @strIncomeTax
================================</pre>
This would produce:
Payroll Evaluation -------------------------------- Payroll Frequency: Semimonthly Gross Salary: 1884.68 Income Tax: 1039.44 ================================
When Switching a Value
Introduction
So far, we have seen that, when you are setting up a switch statement, create the desired case clauses in the switch section. The case keyword can be followed by either a constant value or an expression. Here are examples:
switch (number) { case 1: selected = h; break; case 2: selected = he; break; case 3: selected = li; break; }
Pattern matching consists of applying a condition to a case. In a case of a switch statement, you can include a conditional statement that compares its value to another to actually validate the case. This is done using the when keyword. The formula to follow is:
case value-or-expression when logical-expression: statement(s)
As mentioned already, the case is followed by a constant or an expression, The new keyword is when. It is followed by a logical expression.
We are starting a sample application named "Metropolitan Delivery". It is a (fictitious) company that owns various types of vehicles that are used by employees to deliver various types of merchandise. The pay of the employees is based on various factors. The deliveries made by the company are in three categories. The local covered includes the neighborhoods commonly known by employees and the ZIP codes are those close to the company's location. The metropolitan coverage is also an area familiar to the employees, including the cities in the proximity of less than 200 miles of the company's location. Any area beyond that distance is considered as nationwide. The employees are paid on the distance they cover to deliver a merchandise, but the rate depends on the category of coverage. Here is an example:
@page @model PracticalLearning.Pages.Shared.RoadTrafficModel @{ double pieceworkRate = 0.50; string coverageArea = "Unknown"; /* Areas covered * L - Local * M - Metropolitan * N - Nation */ string coverage = "l"; if((coverage == "l") || (coverage == "L")) coverageArea = "Local"; else if((coverage == "m") || (coverage == "M")) coverageArea = "Metropolitan"; else if((coverage == "n") || (coverage == "N")) coverageArea = "Nation"; // Miles driven int miles = 22; switch(coverageArea) { case "Local" when miles < 25: pieceworkRate = .46; break; case "Local" when miles >= 25 && miles < 65: pieceworkRate = .62; break; case "Local" when miles >= 65: pieceworkRate = .88; break; case "Metro": pieceworkRate = 1.42; break; case "Nation": pieceworkRate = 1.57; break; } double grossEarnings = miles * pieceworkRate; string strPieceWorkRate = $"{pieceworkRate:f}"; string strGrosseEarning = $"{grossEarnings:f}"; } <pre>============================ -- Metropolitan Delivery -- ---------------------------- Coverage: @coverageArea Miles Driven: @miles Piecework Rate: @strPieceWorkRate ---------------------------- Gross Earnings: @strGrosseEarning ============================</pre>
This would produce:
============================ -- Metropolitan Delivery -- ---------------------------- Coverage: Local Miles Driven: 22 Piecework Rate: 0.46 ---------------------------- Gross Earnings: 10.12 ============================
When Switching a Variable
After a case keyword, you can declare a variable of the same type as the value used in the parentheses of switch(). Follow the variable with the when keyword followed by a logical expression that equates the variable to the case value. The variable is "visible" only with its case. Therefore, you can use the same variable in different case sections.
When Patterning a Conditional Statement
The when expression is used to apply a conditional statement. It can consist of an expression that uses any of the Boolean operators we are familiar with. It may look as follows:
switch(number) { case value-or-expression when number > 8: statement(s); break; }
Patterning Different Types of Values
When using a switch statement, the values involved must be of the same type or compatible. Otherwise, you can find a way to convert them.
Practical Learning: Ending the Lesson
|
|||
Previous | Copyright © 2001-2022, FunctionX | Monday 06 December 2021 | Next |
|