chapter
6
Statements and Exceptions
I
n C#, statements fall into one of three categories: labeled, declaration, and
embedded. This is shown by the following EBNF definition:
EBNF
Stmt = LabeledStmt | DeclStmt | EmbeddedStmt .
Embedded statements include the full gamut of conditional, iterative, and transfer state-
ments that one would expect in any high-level language. Additional constructs for mutual
exclusion and the use of resources are also provided.
In this chapter, we first present one type of embedded statement called the block
statement. Declaration statements and all other embedded statements are then discussed
with particular emphasis on the exception-handling mechanism of C#. Because of their
limited use and appeal, labeled statements are only described in the narrow context of the
goto and switch statements.
6.1 Block Statement
A block is an embedded statement that encloses zero or more statements within a pair of
opening and closing braces:
EBNF
Block = "{" Stmts? "}" .
Each statement in a block is executed in sequence, but the block itself returns no value.
Although a block is not required for only one statement, it is a useful practice to enclose
Tip
a single statement within braces, as would become required if additional statements were
added. For example, if a debugging Write is added to this statement:
if(x>0)
x = temp;
107
108
Chapter 6: Statements and Exceptions
■
then braces are required to enclose the two statements as a single block:
if(x>0){
x = temp;
Console.Write("Value of x is {0}.", x);
}
Finally, if code is not reachable within a block, then a compilation error is generated.
6.2 Declaration Statements
A declaration statement declares and initializes one or more local variables or constants
of a given type. In the case of a constant, the type must be preceded by the keyword
const and the initialization must be explicit. Variables need not be explicitly initialized
upon declaration since number, character, and reference-type variables are initialized by
default to 0, ‘\0’, and null, respectively. The complete EBNF definition for declaration
statements is given here:
EBNF
DeclStmt = ( LocalVariableDecl | LocalConstantDecl ) ";" .
LocalVariableDecl = Type LocalVariableDecltorList .
LocalVariableDecltor = Identifier ( "=" LocalVariableInitializer )? .
LocalVariableInitializer = Expr | ArrayInitializer .
LocalConstantDecl = "const" Type ConstantDecltorList .
ConstantDecltor = Identifier "=" ConstantExpr .
For example:
float number;
const String name = "Michel";
intn=2,m;
int len[]={1,n,3};
A variable declaration can appear anywhere in a block, and not just at the beginning as in
C. The scope of the variable, however, ranges from its point of declaration to the end of
the innermost block in which it is declared. For example:
{
...
for(intn=0;n<8;n++) {
// n is in the scope of the for
...
}
...
char c; // Declaration closer to its related code
...
}
■
6.3 Embedded Statements
109
Finally, any variable that is used before declaration or is accessed outside its scope
generates a compilation error.
6.3 Embedded Statements
Embedded statements in C# include many of the well-known constructs in C/C++ and
Java, such as block statements (described previously), expression statements, empty state-
ments, selection statements, and iteration statements. A summary of these statements and
others in C# are listed in the following EBNF definition and described in the sections that
follow.
EBNF
EmbeddedStmt = ExprStmt | EmptyStmt | Block | SelectionStmt
| IterationStmt | JumpStmt | TryStmt | CheckedStmt
| UncheckedStmt | LockStmt | UsingStmt | YieldStmt .
6.3.1 Expression and Empty Statements
An expression statement is simply an expression with a semicolon at the end. However,
only the following types of expressions can become statements:
■
Method invocations,
■
Object creation expressions (with new),
■
Assignment expressions containing = or op= operators, and
■
Expressions with ++ and -- operators (prefix or postfix).
The complete EBNF definition of an expression statement is given here:
EBNF
ExprStmt = StmtExpr ";" .
StmtExpr = InvocationExpr | ObjectCreationExpr | Assignment |
PostIncExpr | PostDecExpr | PreIncExpr | PreDecExpr .
An empty statement, on the other hand, is simply represented by a semicolon.
EBNF
EmptyStmt = ";" .
An empty statement is often used in conjunction with the for statement as illustrated
here:
for(i=0;i<n && A[i]!=x; i++)
; // Empty statement
In this case, all the necessary comparisons and assignments that search for value x in array
A of size n are encapsulated as part of the control mechanism of the for statement itself.
110
Chapter 6: Statements and Exceptions
■
6.3.2 Selection Statements
Selection statements allow a program to choose one of a number of possible actions for
execution. These selection statements include the if and switch statements.
if Statement
The syntax of the if statement is:EBNF
IfStmt = "if" "(" BooleanExpr ")" EmbeddedStmt1 ( "else" EmbeddedStmt2 )? .
where the else part of the if statement is optional. If the condition specified by
BooleanExpr evaluates to true then the action specified by EmbeddedStmt1 is performed.
Otherwise, EmbeddedStmt2 is executed whenever present. Two variations of the if
statement, with and without the else part, are illustrated in the following single
example:
bool directionUp;
...
if (directionUp) { // If statement with an else part
if (++count > max) { // Nested if statement without an else part
count = min;
return true;
}
} else {
if (--count < min) { // Nested if statement without an else part
count = max;
return true;
}
}
return false;
Another variation of the if statement uses the else if clause to select one of many alterna-
tives. In the following example, this variation selects one of four alternatives based on the
value of an operator character. A similar example using the switch statement is presented
in the next subsection.
char operator;
...
if (operator == ‘+’) {
...
} else if (operator == ‘-’) {
...
} else if (operator == ‘*’) {
...
■
6.3 Embedded Statements
111
} else { // Default case
...
}
switch Statement
The switch statement is used to choose one of many alternative actions based on the value
of an expression Expr as shown here:
EBNF
SwitchStmt = "switch" "(" Expr ")" SwitchBlock .
SwitchBlock = "{" SwitchSections? "}" .
SwitchSection = SwitchLabels StmtList .
SwitchLabel = ( "case" ConstantExpr ":")|("default" ":" ) .
A switch statement is executed as follows:
■
The switch expression is evaluated. Only expressions that evaluate to an integral,
character, enumerated, or string type are permitted.
■
If one of the case label constants is equal to the expression, control is transferred
to the list of statement(s) following the case label that is matched. After execution
of the associated statement(s), a break statement must be used to reach the end of
the switch statement. Unlike C/C++ and Java, control does not fall through to the
next case section unless a goto statement is used. In fact, the traditional fall-through
strategy results in a compilation error in C#.
■
If no case label is equal to the value of the expression, the default label (if any) is
executed.
Example:
char op;
long int1, int2;
...
switch (op) {
case ‘+’: Console.WriteLine(" = {0}", int1 + int2); break;
case ‘-’: Console.WriteLine(" = {0}", int1 - int2); break;
case ‘x’: goto case ‘*’; // To obtain a fall through
case ‘*’: Console.WriteLine(" = {0}", int1 * int2); break;
case ‘/’: if ( int2 != 0 )
Console.WriteLine(" = {0}", int1 / int2);
else
Console.WriteLine("Divide by zero");
break;
default: Console.WriteLine("Invalid operator: must be+-*x/");
break;
}
112
Chapter 6: Statements and Exceptions
■
6.3.3 Iteration Statements
Iteration statements, or loops, allow a single statement or block to be executed repeat-
edly. The loop condition is a boolean expression that determines when to terminate the
loop. C# provides four kinds of loops: while, do-while, for, and foreach statements.
while Statement
The syntax of the while loop is:EBNF
WhileStmt = "while" "(" BooleanExpr ")" EmbeddedStmt .
EmbeddedStmt is executed zero or more times until the BooleanExpr evaluates to false.
Example:
Console.Write("Countdown: ");
int sec = 9;
while ( sec >= 0 )
Console.Write("{0} ", sec--);
Console.WriteLine("... Go!");
Output:
Countdown:9876543210...Go!
do-while Statement
The syntax of the do-while loop is:EBNF
DoStmt = "do" EmbeddedStmt "while" "(" BooleanExpr ")" ";" .
EmbeddedStmt is executed one or more times until the BooleanExpr evaluates to
false.
Example (giving the same output):
Console.Write("Countdown: ");
int sec = 9;
do
Console.Write("{0} ", sec--);
while ( sec >= 0 );
Console.WriteLine("... Go!");
■
6.3 Embedded Statements
113
for Statement
The syntax of the for loop is: EBNF
ForStmt = "for" "(" ForInitializer? ";" ForCondition? ";" ForIterator? ")"
EmbeddedStmt .
and is equivalent to the following statements:
ForInitializer
"while" "(" ForCondition ")" "{"
EmbeddedStmt
ForIterator
"}"
where:
EBNF
ForInitializer = LocalVarDecl | StmtExprList .
ForCondition = BooleanExpr .
ForIterator = StmtExprList .
Example (giving the same output):
Console.Write("Countdown: ");
for (int sec = 9; sec >= 0; --sec)
Console.Write("{0} ", sec);
Console.WriteLine("... Go!");
An infinite for loop that prints dots:
for (;;)
Console.Write(".");
is equivalent to the following while statement:
while (true)
Console.Write(".");
foreach Statement
The syntax of the foreach loop is:
EBNF
ForeachStmt = "foreach" "(" Type Identifier "in" Expr ")" EmbeddedStmt .
The foreach statement enumerates the elements of a given collection and executes the
embedded statement for each one. The Type and Identifier declare a read-only itera-
tion variable to be used locally within the scope of the embedded statement. During the
loop execution, this iteration variable represents a collection element. A compilation error
114
Chapter 6: Statements and Exceptions
■
occurs if the variable is (1) modified via assignment or the ++ and -- operators or (2) passed
as a ref or out parameter.
Example:
int[] evenNumbers={2,4,6,8};
foreach (int n in evenNumbers)
Console.Write("{0} ", n);
Console.WriteLine();
Output:
2468
6.3.4 Jump Statements
C# offers five kinds of jump statements that unconditionally transfer control in an
application: goto, continue, break, return, and exception handling (throw and try) state-
ments. Because of its importance, exception handling is discussed separately in the next
section.
goto and Labeled Statements
A labeled statement allows a statement to be preceded by an Identifier label. Labels
are permitted within blocks only, and their scope includes any nested blocks.
EBNF
LabeledStmt = Identifier ":" EmbeddedStmt .
In C#, the name of an identifier label never conflicts with any other identifier for local
variables, fields, and so on. Outside the normal sequence of execution, a labeled statement
is reached by using a goto statement within the same scope (or block). In general, the goto
statement transfers control to any statement that is marked by a label including a case
label as defined here:
EBNF
GotoStmt = "goto" ( Identifier | ("case" ConstantExpr) | "default" ) ";" .
The goto statement must be within the scope of the label. Otherwise, a compilation error
is generated.
continue Statement
The continue statement starts a new iteration of the innermost enclosing while, do-while,
for,orforeach by prematurely ending the current iteration and proceeding with the next
iteration, if possible.
EBNF
ContinueStmt = "continue" ";" .