446 lines
13 KiB
Markdown
446 lines
13 KiB
Markdown
# Introduction
|
||
|
||
The C# programming language is similar to any human written or spoken language.
|
||
They each support different ways of expressing the same idea. In spoken
|
||
languages, some words and phrases are more descriptive, accurate, or succinct
|
||
than others. In the C# programming language, there is more than one way to
|
||
create branching logic. For example, selections that use `if` statements and
|
||
selections that use `switch` statements. Depending on the context of your
|
||
application, one type of selection statement might be more expressive and
|
||
succinct than the other.
|
||
|
||
Suppose working on applications that make extensive use of selections
|
||
statements. In some cases, `if-elseif-else` constructs are used to produce
|
||
succinct and expressive code that is easy to read and maintain. In other cases,
|
||
the `if-elseif-else` constructs produce the required result, but are difficult
|
||
to read and maintain. You have been tasked with reviewing the code and
|
||
determining when it is suitable to use a `switch` statement rather than an `if`
|
||
statement.
|
||
|
||
In this module, you'll investigate the use of a `switch` statement to implement
|
||
branching logic as an alternative to an `if` statement. You'll also work on
|
||
converting an `if-elseif-else` construct to a `switch-case` construct. During
|
||
this process, you'll learn to recognize the benefits of choosing one type of
|
||
selection statement over the other.
|
||
|
||
By the end of this module, you'll be able to implement `switch` statements in
|
||
your application, judge when to use a `switch` statement over an
|
||
`if-elseif-else` construct, and convert `if-elseif-else` constructs to `switch`
|
||
statements.
|
||
|
||
### Learning objectives
|
||
|
||
In this module, you will:
|
||
|
||
- Use the `switch-case` construct to match a variable or expression against
|
||
several possible outcomes.
|
||
- Convert code that uses an `if-elseif-else` construct into a `switch-case`
|
||
construct.
|
||
|
||
---
|
||
|
||
## Exercise
|
||
|
||
### Implement a switch statement
|
||
|
||
A `switch` statement is a C# selection statement that provides an alternative
|
||
to an `if-elseif-else` branching construct. The `switch` statement provides
|
||
advantages over an `if-elseif-else` construct when evaluating a single value
|
||
against a list of known matching values.
|
||
|
||
Consider the following scenario:
|
||
|
||
- You're working on an application related to food nutrition. A section of the
|
||
code deals with fruits.
|
||
- Your code includes a variable named `fruit` that's used to hold the name of
|
||
different types of fruit.
|
||
- You have a list of the 20 fruits that your application is focused on.
|
||
- You want to branch your code based on the value assigned to `fruit`.
|
||
|
||
In this scenario, you can use a `switch` statement to create a separate branch
|
||
for each type of fruit.
|
||
|
||
### How does a switch statement work?
|
||
|
||
The `switch` statement chooses one section of code to execute from a list of
|
||
possible switch sections. The selected switch section is chosen based on a
|
||
pattern match with the statement's match expression.
|
||
|
||
Consider the following code sample that shows the basic structure of `switch`
|
||
statement:
|
||
|
||
```cs
|
||
switch (fruit) {
|
||
case "apple":
|
||
Console.WriteLine($"App will display information for apple.");
|
||
break;
|
||
case "banana":
|
||
Console.WriteLine($"App will display information for banana.");
|
||
break;
|
||
case "cherry":
|
||
Console.WriteLine($"App will display information for cherry.");
|
||
break;
|
||
}
|
||
```
|
||
|
||
The match expression (which may also be referred to as the switch expression)
|
||
is the value following the `switch` keyword, in this case (`fruit`). Each
|
||
*switch* section is defined by a *case pattern*. Case patterns are constructed
|
||
using the keyword `case` followed by a value. The first case pattern in this
|
||
example is: `case "apple":`. Case patterns are Boolean expressions that
|
||
evaluate to either `true` or `false`. Each switch section includes a small
|
||
number of code lines that will be executed if the case pattern is a match for
|
||
the match expression. In this example, if `fruit` is assigned a value of
|
||
"apple", the first case pattern will evaluate as `true` and that switch section
|
||
will be executed.
|
||
|
||
A switch statement must include at least one switch section, but will normally
|
||
contain three or more switch sections.
|
||
|
||
The switch is best used when:
|
||
|
||
- You have a single value (variable or expression) that you want to match
|
||
against many possible values.
|
||
- For any given match, you need to execute a couple of lines of code at most.
|
||
|
||
> Note
|
||
> This first example of a `switch` statement is purposefully simple and your
|
||
examination of the syntax was brief. You will be examining additional features
|
||
of the `switch` statement when you work through some more advanced scenarios
|
||
in the sections below.
|
||
|
||
It's time to prepare your coding environment and begin developing your own
|
||
`switch` statements.
|
||
|
||
#### Prepare your coding environment
|
||
|
||
At the Terminal command prompt, to create a new console application in a
|
||
specified folder, type dotnet new console -o ./path_to/TestProject and then
|
||
press Enter.
|
||
|
||
This .NET CLI command uses a .NET program template to create a new C# console
|
||
application project in the specified folder location.
|
||
|
||
#### Create and test a switch statement
|
||
|
||
Type the following code into the editor:
|
||
|
||
```cs
|
||
int employeeLevel = 200;
|
||
string employeeName = "John Smith";
|
||
|
||
string title = "";
|
||
|
||
switch (employeeLevel) {
|
||
case 100:
|
||
title = "Junior Associate";
|
||
break;
|
||
case 200:
|
||
title = "Senior Associate";
|
||
break;
|
||
case 300:
|
||
title = "Manager";
|
||
break;
|
||
case 400:
|
||
title = "Senior Manager";
|
||
break;
|
||
default:
|
||
title = "Associate";
|
||
break;
|
||
}
|
||
|
||
Console.WriteLine($"{employeeName}, {title}");
|
||
```
|
||
|
||
The Program.cs file must be saved before building or running the code.
|
||
|
||
At the Terminal command prompt, to run your code, type `dotnet run` and then
|
||
press Enter.
|
||
|
||
Output
|
||

|
||
```txt
|
||
John Smith, Senior Associate
|
||
```
|
||
|
||
Take a minute to review the `switch` statement that you entered.
|
||
|
||
Notice that the `switch` statement defines a single code block.
|
||
|
||
The `switch` statement defines a single code block that includes a list of
|
||
`switch` sections. To the right of the switch keyword is a *switch expression*
|
||
that's enclosed in parentheses.
|
||
|
||
Notice the list of switch sections inside the code block.
|
||
|
||
The `switch` code block contains a list of switch sections, each of which
|
||
includes one or more switch labels. In addition, each switch section includes
|
||
a statement list that will execute if the label is equal to the switch
|
||
expression defined at the top of the switch statement.
|
||
|
||
The switch expression is evaluated against the case labels from top to bottom
|
||
until a value that is equal to the switch expression is found. If none of the
|
||
labels are a match, the statement list for the `default` case will be executed.
|
||
If no default is included, control is transferred to the end point of the
|
||
switch statement. Each label must provide a value type that matches the type
|
||
specified in the switch expression.
|
||
|
||
> Note
|
||
> The optional `default` label can appear at any position within the list of
|
||
switch sections. However, most developers choose to put it last because it
|
||
makes more sense (logically) to position `default` as the final option.
|
||
Regardless of the position, the `default` section will be evaluated last.
|
||
|
||
In our example:
|
||
|
||
- the switch expression is `(employeeLevel)`
|
||
- each switch section has a single switch label (`case` or `default`).
|
||
- the matching switch section is defined by `case: 200`, since
|
||
`employeeLevel = 200`.
|
||
|
||
Notice that each switch section is separated from the next.
|
||
|
||
Only one switch section is allowed to be executed. This means that execution
|
||
of a switch section is not permitted to “fall through” to the next switch
|
||
section. The `break` keyword is one of several ways to end a switch section
|
||
before it gets to the next section. If you forget the `break` keyword (or,
|
||
optionally, the `return` keyword) the compiler will generate an error.
|
||
|
||
#### Change the level variable value to see how the switch statement evaluates it
|
||
|
||
To exercise the default case, let's change the employee's level by modifying the value assignment.
|
||
|
||
To modify the value assigned to `employeeLevel`, update your code as follows:
|
||
|
||
```cs
|
||
int employeeLevel = 201;
|
||
```
|
||
|
||
Save your code file, and then run your code.
|
||
|
||
Enter `dotnet run` from the Terminal command prompt to run your code.
|
||
|
||
Notice that the output has changed.
|
||
|
||
Now, when you run the code, you should see the more generic title used.
|
||
|
||
```txt
|
||
John Smith, Associate
|
||
```
|
||
|
||
Since the `employeeLevel` doesn't match any labels, the `default` label is
|
||
matched.
|
||
|
||
#### Modify a switch section to include multiple labels
|
||
|
||
Suppose our company decided to give all level 100 employees the title "Senior
|
||
Associate" -- the same title as level 200 employees. As the developer, you
|
||
decide to implement this by removing the first switch section belonging to the
|
||
label `case 100:`, and instead allow both the `case 100:` and `case 200:` labels
|
||
to execute the same switch section.
|
||
|
||
To modify the value assigned to employeeLevel, update your code as follows:
|
||
|
||
```cs
|
||
int employeeLevel = 100;
|
||
```
|
||
|
||
To assign multiple labels to the first switch section, update your code as follows:
|
||
|
||
```cs
|
||
case 100:
|
||
case 200:
|
||
title = "Senior Associate";
|
||
break;
|
||
```
|
||
|
||
When you're finished making changes, your modifications should match the
|
||
following code:
|
||
|
||
```cs
|
||
int employeeLevel = 100;
|
||
string employeeName = "John Smith";
|
||
|
||
string title = "";
|
||
|
||
switch (employeeLevel) {
|
||
case 100:
|
||
case 200:
|
||
title = "Senior Associate";
|
||
break;
|
||
case 300:
|
||
title = "Manager";
|
||
break;
|
||
case 400:
|
||
title = "Senior Manager";
|
||
break;
|
||
default:
|
||
title = "Associate";
|
||
break;
|
||
}
|
||
|
||
Console.WriteLine($"{employeeName}, {title}");
|
||
```
|
||
|
||
Save your code file, and then run your code.
|
||
|
||
Enter `dotnet run` from the Terminal command prompt to run your code.
|
||
|
||
You should see the following output:
|
||
|
||
```txt
|
||
John Smith, Senior Associate
|
||
```
|
||
|
||
Both of the case labels `100` and `200` are now paired with the switch section
|
||
that sets the title to the string value `Senior Associate`.
|
||
|
||
### Recap
|
||
|
||
Here's the main takeaways you learned about the switch statement:
|
||
|
||
- Use the `switch` statement when you have one value with many possible matche
|
||
s, each match requiring a branch in your code logic.
|
||
- A single switch section containing code logic can be matched using one or
|
||
more labels defined by the `case` keyword.
|
||
- Use the optional `default` keyword to create a label and a switch section
|
||
that will be used when no other case labels match.
|
||
|
||
---
|
||
|
||
## Exercise
|
||
|
||
### Complete a challenge activity using switch statements
|
||
|
||
Code challenges will reinforce what you've learned, and help you gain some
|
||
confidence before continuing on.
|
||
|
||
### Convert to switch statements challenge
|
||
|
||
In this challenge, you'll rewrite an `if-elseif-else` construct as a `switch`
|
||
statement. This challenge should help you see the strengths/weaknesses of the
|
||
`switch` statement when compared to an `if-elseif-else` construct. Good luck.
|
||
|
||
### Code challenge: rewrite if-elseif-else using a switch statement
|
||
|
||
You'll start with code that uses an `if-elseif-else` construct to evaluate the
|
||
components of a product SKU. The SKU (Stock Keeping Unit) is formatted using
|
||
three coded values: `<product #>-<2-letter color code>-<size code>`. For
|
||
example, a SKU value of `01-MN-L` corresponds to (sweat shirt)-(maroon)-(large),
|
||
and the code outputs a description that appears as "Product: Large Maroon
|
||
Sweat shirt".
|
||
|
||
Your challenge is to convert the `if` statement code to a `switch` statement
|
||
that achieves the same result as the initial code.
|
||
|
||
Enter the following code into the code editor:
|
||
|
||
```cs
|
||
// SKU = Stock Keeping Unit.
|
||
// SKU value format: <product #>-<2-letter color code>-<size code>
|
||
string sku = "01-MN-L";
|
||
|
||
string[] product = sku.Split('-');
|
||
|
||
string type = "";
|
||
string color = "";
|
||
string size = "";
|
||
|
||
if (product[0] == "01") {
|
||
type = "Sweat shirt";
|
||
} else if (product[0] == "02") {
|
||
type = "T-Shirt";
|
||
} else if (product[0] == "03") {
|
||
type = "Sweat pants";
|
||
} else {
|
||
type = "Other";
|
||
}
|
||
|
||
if (product[1] == "BL") {
|
||
color = "Black";
|
||
} else if (product[1] == "MN") {
|
||
color = "Maroon";
|
||
} else {
|
||
color = "White";
|
||
}
|
||
|
||
if (product[2] == "S") {
|
||
size = "Small";
|
||
} else if (product[2] == "M") {
|
||
size = "Medium";
|
||
} else if (product[2] == "L") {
|
||
size = "Large";
|
||
} else {
|
||
size = "One Size Fits All";
|
||
}
|
||
|
||
Console.WriteLine($"Product: {size} {color} {type}");
|
||
```
|
||
|
||
Update the code to use a `switch` statement in place of the `if-elseif-else`
|
||
construct.
|
||
|
||
Verify that your output hasn't changed.
|
||
|
||
No matter how you do it, your code should produce the following output:
|
||
|
||
Output
|
||

|
||
```txt
|
||
Product: Large Maroon Sweat shirt
|
||
```
|
||
|
||
```cs
|
||
string sku = "01-MN-L";
|
||
|
||
string[] product = sku.Split('-');
|
||
|
||
string type = "";
|
||
string color = "";
|
||
string size = "";
|
||
|
||
switch (product[0]) {
|
||
case "01":
|
||
type = "Sweat shirt";
|
||
break;
|
||
case "02":
|
||
type = "T-Shirt";
|
||
break;
|
||
case "03":
|
||
type = "Sweat pants";
|
||
break;
|
||
default:
|
||
type = "Other";
|
||
break;
|
||
}
|
||
|
||
switch (product[1]) {
|
||
case "BL":
|
||
color = "Black";
|
||
break;
|
||
case "MN":
|
||
color = "Maroon";
|
||
break;
|
||
default:
|
||
color = "White";
|
||
break;
|
||
}
|
||
|
||
switch (product[2]) {
|
||
case "S":
|
||
size = "Small";
|
||
break;
|
||
case "M":
|
||
size = "Medium";
|
||
break;
|
||
case "L":
|
||
size = "Large";
|
||
break;
|
||
default:
|
||
size = "One Size Fits All";
|
||
break;
|
||
}
|
||
|
||
Console.WriteLine($"Product: {size} {color} {type}");
|
||
```
|