|
|
8 Module 4: Statements and Exceptions
Examples
You can use a simple embedded if statement such as the following:
if (number % 2 == 0)
Console.WriteLine("even" ;
Although braces are not required in embedded statements, many style guides
recommend using them because they make your code less error prone and
easier to maintain. You can rewrite the previous example with braces as follows:
if (number % 2 == 0) {
Console.WriteLine("even" ;
}
You can also use an if statement block such as the following:
if (minute == 60) {
minute = 0;
hour++;
}
Converting Integers to Boolean Values
Implicit conversion from an integer to a Boolean value is a potential source of
bugs. To avoid such conversion-related bugs, C# does not support integer to
Boolean value conversion. This is a significant difference between C# and other
similar languages.
For example, the following statements, which at worst generate warnings in
C and C++, result in compilation errors in C#:
int x;
...
if (x) ... // Must be x != 0 in C#
if (x = 0) ... // Must be x == 0 in C#
Module 4: Statements and Exceptions 9
Cascading if Statements
enum Suit { Clubs, Hearts, Diamonds, Spades };
Suit trumps = Suit.Hearts;
if (trumps == Suit.Clubs)
color = "Black";
else if (trumps == Suit.Hearts)
color = "Red";
else if (trumps == Suit.Diamonds)
color = "Red";
else
color = "Black";
enum Suit { Clubs, Hearts, Diamonds, Spades };
Suit trumps = Suit.Hearts;
if (trumps == Suit.Clubs)
color = "Black";
else if (trumps == Suit.Hearts)
color = "Red";
else if (trumps == Suit.Diamonds)
color = "Red";
else
color = "Black";
You can handle cascading if statements by using an else if statement. C# does
not support the else if statement but forms an else if-type statement from an else
clause and an if statement, as in C and C++. Languages such as Visual Basic
support cascading if statements by using an else if statement between the initial
if statement and the final else statement.
By using the else if construct, you can have any number of branches. However,
the statements controlled by a cascading if statement are mutually exclusive, so
that only one statement from the set of else if constructs is executed.
Nesting if Statements
Nesting one if statement within another if statement creates a potential
ambiguity called a dangling else, as shown in the following example:
if (percent >= 0 && percent <= 100)
if (percent > 50)
Console.WriteLine("Pass" ;
else
Console.WriteLine("Error: out of range" ;
10 Module 4: Statements and Exceptions
The else is indented to the same column as the first if. When you read the code,
it appears that the else does not associate with the second if. This is dangerously
misleading. Regardless of the layout, the compiler binds an else clause to its
nearest if statement. This means that the compiler will interpret the above code
as follows:
if (percent >= 0 && percent <= 100)
{
if (percent > 50)
Console.WriteLine("Pass" ;
else
Console.WriteLine("Error: out of range" ;
}
One way you can make the else associate with the first if is to use a block, as
follows:
if (percent >= 0 && percent <= 100) {
if (percent > 50)
Console.WriteLine("Pass" ;
} else {
Console.WriteLine("Error: out of range" ;
}
It is best to format cascading if statements with proper indentation;
otherwise, long decisions quickly become unreadable and trail off the right
margin of the page or screen.
Tip
Module 4: Statements and Exceptions 11
The switch Statement
n Use switch Statements for Multiple Case Blocks
n Use break Statements to Ensure That No Fall Through
Occurs
switch (trumps) {
case Suit.Clubs :
case Suit.Spades :
color = "Black"; break;
case Suit.Hearts :
case Suit.Diamonds :
color = "Red"; break;
default:
color = "ERROR"; break;
}
switch (trumps) {
case Suit.Clubs :
case Suit.Spades :
color = "Black"; break;
case Suit.Hearts :
case Suit.Diamonds :
color = "Red"; break;
default:
color = "ERROR"; break;
}
The switch statement provides an elegant mechanism for handling complex
conditions that would otherwise require nested if statements. It consists of
multiple case blocks, each of which specifies a single constant and an
associated case label. You cannot group a collection of constants together in a
single case label. Each constant must have its own case label.
A switch block can contain declarations. The scope of a local variable or
constant that is declared in a switch block extends from its declaration to the
end of the switch block, as is shown in the example on the slide.
Execution of switch Statements
A switch statement is executed as follows:
1. If one of the constants specified in a case label is equal to the value of the
switch expression, control is transferred to the statement list following the
matched case label.
2. If no case label constant is equal to the value of the switch expression, and
the switch statement contains a default label, control is transferred to the
statement list following the default label.
3. If no case label constant is equal to the value of the switch expression, and
the switch statement does not contain a default label, control is transferred
to the end of the switch statement.
12 Module 4: Statements and Exceptions
You can use a switch statement to evaluate only the following types of
expressions: any integer type, a char, an enum, or a string. You can also
evaluate other expression types by using the switch statement, as long as there
is exactly one user-defined explicit conversion from the disallowed type to one
of the allowed types.
Unlike in Java, C, or C++, the governing type of a switch statement in
C# can be a string. With a string expression, the value null is permitted as a
case label constant.
For more information about conversion operators, search for “conversion
operators” in the .NET Framework SDK Help documents.
Grouping Constants
To group several constants together, repeat the keyword case for each constant,
as shown in the following example:
enum MonthName { January, February, ..., December };
MonthName current;
int monthDays;
...
switch (current) {
case MonthName.February :
monthDays = 28;
break;
case MonthName.April :
case MonthName.June :
case MonthName.September :
case MonthName.November :
monthDays = 30;
break;
default :
monthDays = 31;
break;
}
You use the case and default labels only to provide entry points for the control
flow of the program based on the value of the switch expression. They do not
alter the control flow of the program.
The values of the case label constants must be unique. This means that you
cannot have two constants that have the same value. For example, the following
example will generate a compile-time error:
switch (trumps) {
case Suit.Clubs :
case Suit.Clubs : // Error: duplicate label
...
default :
default : // Error: duplicate label again
}
Note
Module 4: Statements and Exceptions 13
Using break in switch Statements
Unlike in Java, C, or C++, C# statements associated with one or more case
labels cannot silently fall through or continue to the next case label. A silent fall
through occurs when execution proceeds without generating an error. In other
words, you must ensure that the last statement associated with a set of case
labels does not allow the control flow to reach the next set of case labels.
Statements that help you to fulfill this requirement, known as the no fall
through rule, are the break statement (probably the most common), the goto
statement (very rare), the return statement, the throw statement, and an infinite
loop.
The following example will generate a compile-time error because it breaks the
no fall through rule:
switch (days % 10) {
case 1 :
if (days / 10 != 1) {
suffix = "st";
break;
}
// Error: fall through here
case 2 :
if (days / 10 != 1) {
suffix = "nd";
break;
}
// Error: fall through here
case 3 :
if (days / 10 != 1) {
suffix = "rd";
break;
}
// Error: fall through here
default :
suffix = "th";
// Error: fall through here
} |
|