The C# Station Tutorial
by Joe Mayo, 9/2/00, updated 10/6/01, 3/12/03, 1/11/04, 1/25/05, 2/21/08, and
4/29/08
Lesson 3: Control Statements - Selection
In the last couple of lessons, every program you saw contained a limited amount
of sequential steps and then stopped. There were no decisions you could make with
the input and the only constraint was to follow straight through to the end. The
information in this lesson will help you branch into separate logical sequences
based on decisions you make. More specifically, the goals of this lesson are as
follows:
- Learn the if statements.
- Learn the switch statement.
- Learn how break is used in switch statements.
- Understand proper use of the goto statement.
The if Statement
An if statement allows you to take different paths of logic, depending
on a given condition. When the condition evaluates to a boolean true, a
block of code for that true condition will execute. You have the option of a single
if statement, multiple else if statements, and an optional else
statement. Listing 3-1 shows how each of these types of if statements work.
Listing 3-1. forms of the if statement: IfSelection.cs
-
using System;
class IfSelect
{
public static void Main()
{
string myInput;
int myInt;
-
Console.Write("Please enter a number:
");
myInput = Console.ReadLine();
myInt = Int32.Parse(myInput);
-
// Single Decision and Action with brackets
if (myInt > 0)
{
Console.WriteLine("Your
number {0} is greater than zero.", myInt);
}
-
// Single Decision and Action without brackets
if (myInt < 0)
Console.WriteLine("Your
number {0} is less than zero.", myInt);
-
// Either/Or Decision
if (myInt != 0)
{
Console.WriteLine("Your
number {0} is not equal to zero.", myInt);
}
else
{
Console.WriteLine("Your
number {0} is equal to zero.", myInt);
}
-
// Multiple Case Decision
if (myInt < 0 || myInt == 0)
{
Console.WriteLine("Your
number {0} is less than or equal to zero.", myInt);
}
else if (myInt > 0 && myInt <= 10)
{
Console.WriteLine("Your
number {0} is in the range from 1 to 10.", myInt);
}
else
if (myInt > 10 && myInt
<= 20)
{
Console.WriteLine("Your
number {0} is in the range from 11 to 20.", myInt);
}
else if (myInt > 20 && myInt <= 30)
{
Console.WriteLine("Your
number {0} is in the range from 21 to 30.", myInt);
}
else
{
Console.WriteLine("Your
number {0} is greater than 30.", myInt);
}
}
}
Get Setup Instructions For How to Run
this Program
The statements in Listing 3-1 use the same input variable, myInt as a part
of their evaluations. This is another way of obtaining interactive input from the
user. Here's the pertinent code:
Console.Write("Please enter
a number: ");
myInput = Console.ReadLine();
myInt = Int32.Parse(myInput);
We first print the line "Please enter a number: " to the console. The Console.ReadLine()
statement causes the program to wait for input from the user, who types a number
and then presses Enter. This number is returned in the form of a string into the
myInput variable, which is a string type. Since we must evaluate the user's
input in the form of an int, myInput must be converted. This is done with
the command Int32.Parse(myInput). (Int32 and similar types
will be covered in another lesson on advanced types) The result is placed into the
myInt variable, which is an int type.
Now that we have a variable in the type we wanted, we will evaluate it with if
statements. The first statement is of the form if (boolean expression) { statements
}, as shown below:
// Single Decision and Action with brackets
if (myInt > 0)
{
Console.WriteLine("Your
number {0} is greater than zero.", myInt);
}
You must begin with the keyword if. Next is the boolean expression between
parenthesis. This boolean expression must evaluate to a true or false
value. In this case, we are checking the user's input to see if it is greater than
(>) 0. If this expression evaluates to true, we execute the statements
within the curly braces. (We refer to the structure with curly braces as a "block")
There could be one or more statements within this block. If the boolean expression
evaluates to false, we ignore the statements inside the block and continue
program execution with the next statement after the block.
Note: In other languages, such as C and C++, conditions can be evaluated
where a result of 0 is false and any other number is true. In C#, the condition
must evaluate to a boolean value of either true or false. If you need to simulate
a numeric condition with C#, you can do so by writing it as (myInt != 0), which
means that the expression evaluate to true if myInt is not 0.
The second if statement is much like the first, except it does not have
a block, as shown here:
// Single Decision and Action without brackets
if (myInt < 0)
Console.WriteLine("Your
number {0} is less than zero.", myInt);
If its boolean expression evaluates to true, the first statement after
the boolean expression will be executed. When the boolean expression evaluates to
false, the first statement after the boolean expression will be skipped
and the next program statement will be executed. This form of if statement
is adequate when you only have a single statement to execute. If you want to execute
two or more statements when the boolean expression evaluates to true, you
must enclose them in a block.
My personal recommendation is to make it a habit to always put your if
statements within a block, regardless of whether or not you have only one statement
to execute. This will help avoid mistakes where you later decide to add a statement
and forget to add the curly braces.
Most of the time, you'll want to make an either/or kind of decision. This is called
an if/else statement. The third if statement in Listing 3-1 presents this
idea, as shown below:
// Either/Or Decision
if (myInt != 0)
{
Console.WriteLine("Your
number {0} is not equal to zero.", myInt);
}
else
{
Console.WriteLine("Your
number {0} is equal to zero.", myInt);
}
When the boolean expression evaluates to true, the statement(s) in the
block immediately following the if statement are executed. However, when
the boolean expression evaluates to false, the statements in the block
following the else keyword are executed.
When you have multiple expressions to evaluate, you can use the if/else if/else
form of the if statement. We show this form in the fourth if statement
of Listing 3-1, and repeated below:
// Multiple Case Decision
if (myInt < 0 || myInt == 0)
{
Console.WriteLine("Your
number {0} is less than or equal to zero.", myInt);
}
else if (myInt > 0 && myInt <= 10)
{
Console.WriteLine("Your
number {0} is in the range from 1 to 10.", myInt);
}
else
if (myInt > 10 && myInt
<= 20)
{
Console.WriteLine("Your
number {0} is in the range from 11 to 20.", myInt);
}
else if (myInt > 20 && myInt <= 30)
{
Console.WriteLine("Your
number {0} is in the range from 21 to 30.", myInt);
}
else
{
Console.WriteLine("Your
number {0} is greater than 30.", myInt);
}
This example begins with the if keyword, again executing the following
block if the boolean expression evaluates to true. However, this time you
can evaluate multiple subsequent conditions with the else if keyword combination.
the else if statement also takes a boolean expression, just like the if
statement. The rules are the same, when the boolean expression for the else if
statement evaluates to true, the block immediately following the
boolean expression is executed. When none of the other if or else if boolean expressions evaluate
to true, the block following the else keyword will be executed.
Only one section of an if/else if/else statement will be executed.
One difference in the last statement from the others is the boolean expressions.
The boolean expression, (myInt < 0 || myInt == 0), contains the conditional
OR (||) operator. In both the regular OR (|) operator and the conditional OR (||)
operator, the boolean expression will evaluate to true if either of the
two sub-expressions on either side of the operator evaluate to true. The
primary difference between the two OR forms are that the regular OR operator will
evaluate both sub-expressions every time. However, the conditional OR will evaluate
the second sub-expression only if the first sub-expression evaluates to false.
The boolean expression, (myInt > 0 && myInt <= 10), contains
the conditional AND operator. Both the regular AND (&) operator and the
conditional AND (&&) operator will return true when both of the
sub-expressions on either side of the operator evaluate to true.
The difference between the two is that the regular AND operator will evaluate both
expressions every time. However, the conditional AND operator will evaluate the
second sub-expression only when the first sub-expression evaluates to true.
The conditional operators (&& and ||) are commonly called short-circuit
operators because they do not always evaluate the entire expression. Thus, they
are also used to produce more efficient code by ignoring unnecessary logic.
The switch Statement
Another form of selection statement is the switch statement, which executes
a set of logic depending on the value of a given parameter. The types of the values
a switch statement operates on can be booleans, enums, integral types, and strings.
Lesson 2: Operators, Types, and Variables discussed
the bool type, integral types and strings and Lesson 17: Enums
will teach you what an enum type is. Listing 3-2 shows how to use the switch
statement with both int and string types.
Listing 3-2. Switch Statements: SwitchSelection.cs
using System;
class SwitchSelect
{
public static void Main()
{
string myInput;
int myInt;
begin:
Console.Write("Please enter a number
between 1 and 3: ");
myInput = Console.ReadLine();
myInt = Int32.Parse(myInput);
// switch with integer type
switch (myInt)
{
case 1:
Console.WriteLine("Your number is {0}.", myInt);
break;
case 2:
Console.WriteLine("Your number is {0}.", myInt);
break;
case 3:
Console.WriteLine("Your number is {0}.", myInt);
break;
default:
Console.WriteLine("Your number {0} is not between 1 and 3.", myInt);
break;
}
decide:
Console.Write("Type \"continue\" to go
on or \"quit\" to stop: ");
myInput = Console.ReadLine();
// switch with string type
switch (myInput)
{
case "continue":
goto begin;
case "quit":
Console.WriteLine("Bye.");
break;
default:
Console.WriteLine("Your input {0} is incorrect.", myInput);
goto decide;
}
}
}
Get Setup Instructions For How to Run
this Program
Note: Listing 3-2 will throw an exception if you enter any value other
than an int. i.e. the letter 'a' would be an error. You can visit
Lesson 15: Introduction to Exception Handling to
learn more about how to anticipate and handle these type of problems.
Listing 3-2 shows a couple of switch statements. The switch statement
begins with the switch keyword followed by the switch expression.
In the first switch statement in listing 3-2, the switch expression
evaluates to an int type, as follows:
// switch with integer type
switch (myInt)
{
case 1:
Console.WriteLine("Your number is {0}.", myInt);
break;
case 2:
Console.WriteLine("Your number is {0}.", myInt);
break;
case 3:
Console.WriteLine("Your number is {0}.", myInt);
break;
default:
Console.WriteLine("Your number {0} is not between 1 and 3.", myInt);
break;
}
The switch block follows the switch expression, where one or more
choices are evaluated for a possible match with the switch expression.
Each choice is labeled with the case keyword, followed by an example that
is of the same type as the switch expression and followed by a colon (:).
In the example we have case 1:, case 2:, and case 3:.
When the result evaluated in the switch expression matches one of these
choices, the statements immediately following the matching choice are executed,
up to and including a branching statement, which could be either a break,
continue, goto , return, or throw statement.
table 3-1 summarizes the branching statements.
Table 3-1. C# Branching Statements
|
Branching statement
|
Description
|
|
break
|
Leaves the switch block
|
|
continue
|
Leaves the switch block, skips remaining logic in enclosing loop, and goes back
to loop condition to determine if loop should be executed again from the beginning.
Works only if switch statement is in a loop as described in
Lesson 04: Control Statements - Loops.
|
|
goto
|
Leaves the switch block and jumps directly to a label of the form "<labelname>:"
|
|
return
|
Leaves the current method. Methods are described in more detail in
Lesson 05: Methods.
|
|
throw
|
Throws an exception, as discussed in Lesson 15: Introduction
to Exception Handling.
|
You may also include a default choice following all other choices. If none
of the other choices match, then the default choice is taken and its statements
are executed. Although use of the default label is optional, I highly recommend
that you always include it. This will help catch unforeseen circumstances and make
your programs more reliable.
Each case label must end with a branching statement, as described in table
3-1, which is normally the break statement. The break statement
will cause the program to exit the switch statement and begin execution
with the next statement after the switch block. There are two exceptions
to this: adjacent case statements with no code in between or using a goto
statement. Here's an example that shows how to combine case statements:
switch (myInt)
{
case 1:
case 2:
case 3:
Console.WriteLine("Your number is {0}.", myInt);
break;
default:
Console.WriteLine("Your number {0} is not between 1 and 3.", myInt);
break;
}
By placing case statements together, with no code in-between, you create
a single case for multiple values. A case without any code will automatically fall
through to the next case. The example above shows how the three cases for myInt
equal to 1, 2, or 3, where case 1 and case 2 will fall through
and execute code for case 3.
A case statement can only be an exact match and you can't use logical
conditions. If you need to use logical conditions, you can use an if/else
if/else statement.
Another way to control the flow of logic in a switch statement is by using
the goto statement. You can either jump to another case statement, or jump
out of the switch statement. The second switch statement in Listing 3-2
shows the use of the goto statement, as shown below:
// switch with string type
switch (myInput)
{
case "continue":
goto begin;
case "quit":
Console.WriteLine("Bye.");
break;
default:
Console.WriteLine("Your input {0} is incorrect.", myInput);
goto decide;
}
Note: in the current example, "continue", is a case of the switch statement
-- not the keyword.
The goto statement causes program execution to jump to the label following
the goto keyword. During execution, if the user types in "continue", the
switch statement matches this input (a string type) with the case
"continue": label and executes the "goto begin:" instruction.
The program will then leave the switch statement and start executing the
first program statement following the begin: label. This is effectively
a loop, allowing you to execute the same code multiple times. The loop will end
when the user types the string "quit". This will be evaluated with the
case "quit": choice, which will print "Bye." to the console, break out
of the switch statement and end the program.
Warning: You should not create loops like this. It is *bad* programming style. The
only reason it is here is because I wanted to show you the syntax of the goto
statement. Instead, use one of the structured looping statements, described in Lesson 04: Control Statements - Loops.
When neither the "continue" nor "quit" strings are entered, the "default:"
case will be entered. It will print an error message to the console and
then execute the goto decide: command. This will cause program execution
to jump to the first statement following the decide: label, which will
ask the user if they want to continue or quit. This is effectively another loop.
Clearly, the goto statement is powerful and can, under controlled circumstances,
be useful. However, I must caution you strongly on its use. The goto statement
has great potential for misuse. You could possibly create a very difficult program
to debug and maintain. Imagine the spaghetti code that could be created by random
goto statements throughout a program. In the next lesson, I'll show you
a better way to create loops in your program.
Summary
The if statement can be written in multiple ways to implement different
branches of logic. The switch statement allows a choice among a set of
bool, enum, integral, or string types. You use break,
continue, goto, return, or throw statements
to leave a case statement. Be sure to avoid the goto statement in your
code unless you have an extremely good reason for using it.
In addition to branching based on a condition, it is useful to be able to execute
a block of statements multiple times. A goto statement is not proper or
adequate for such logic. Therefore, I invite you to return for
Lesson 4: Control Statements - Loops. This will be a continuation of the
same topic.
Your feedback and constructive contributions are welcome. Please feel free
to contact me for feedback or comments you may have about this lesson.
Copyright © 2000-2008 C# Station, All Rights Reserved