2.9 Statements

Execution in a C# program is specified by a series of statements that execute sequentially in the textual order in which they appear. All statements in a procedural-based language such as C# are executed for their effect. For instance, a statement may assign an expression to a variable, repeatedly execute a list of statements, or jump to another statement.

So that multiple statements can be grouped together, zero or more statements may be enclosed in braces to form a statement block.

2.9.1 Expression Statements

[variable =]? expr;

An expression statement evaluates an expression, either assigning its result to a variable or generating side effects (i.e., invocation, new, ++, --). An expression statement ends in a semicolon. For example:

x = 5 + 6; // assign result
x++; // side effect
y = Math.Min(x, 20); // side effect and assign result
Math.Min(x, y); // discards result, but ok, there is a side effect
x =  = y; // error, has no side effect, and does not assign result

2.9.2 Declaration Statements

The variable declaration syntax is:

type [variable [ = expr ]?]+ ;

The constant declaration syntax is:

const type [variable = constant-expr]+;

A declaration statement declares a new variable, optionally assigning the result of an expression to that variable. A declaration statement ends in a semicolon.

The scope of a local or constant variable extends to the end of the current block. You cannot declare another local variable with the same name in the current block or in any nested blocks. For example:

bool a = true;
while(a) {
  int x = 5;
  if (x=  =5) {
    int y = 7;
    int x = 2; // error, x already defined
 Console.WriteLine(y); // error, y is out of scope

A constant declaration is like a variable declaration, except that the variable cannot be changed after it has been declared:

const double speedOfLight = 2.99792458E08;
speedOfLight+=10; // error

2.9.3 Selection Statements

C# has many ways to conditionally control the flow of program execution. This section covers the simplest two constructs: the if-else statement and the switch statement. In addition, C# also provides the conditional operator and loop statements that conditionally execute based on a boolean expression. Finally, C# provides object-oriented ways of conditionally controlling the flow of execution, namely virtual method invocations and delegate invocations. The if-else statement
if (Boolean-expr)
 [statement | statement-block]
[ else
 [statement | statement-block] ]?

An if-else statement executes code depending on whether a boolean expression is true. Unlike in C, only a boolean expression is permitted. In this example, the Compare method will return 1 if a is greater than b, -1 if a is less than b, and 0 if a is equal to b.

int Compare(int a, int b) {
   if (a>b)
      return 1;
   else if (a<b)
      return -1;
   return 0;

It is very common to use the && and || and ! operators to test for AND, OR, and NOT conditions. In this example, our GetUmbrellaNeeded method returns an umbrella if it's rainy or sunny (to protect us from the rain or the sun), as long as it's not also windy (since umbrellas are useless in the wind):

Umbrella GetUmbrella (bool rainy, bool sunny, bool windy) {
   if ((rainy || sunny) && ! windy)
      return umbrella;
   return null;
} The switch statement
switch (expr) {
[ case constant-expr : statement* ]*
[ default : statement* ]?

switch statements let you branch program execution based on a selection of possible values a variable may have. switch statements may result in cleaner code than multiple if statements, since switch statements require an expression to be evaluated only once. For instance:

void Award(int x) {
  switch(x) {
    case 1:
    case 2:
    case 3:
    case 4:
      Console.WriteLine("Highly commended");
      Console.WriteLine("Don't quit your day job!");

The switch statement can only evaluate a predefined type (including the string type) or enum, though user-defined types may provide an implicit conversion to these types.

The end of each case statement must be unreachable. This typically means each case statement ends with a jump statement. The options are:

  • Use the break statement to jump to the end of the switch statement (this is by far the most common option).

  • Use the goto case <constant expression> or goto default statements to jump to either another case statement or to the default case statement.

  • Use any other jump statementnamely, return, throw, continue, or goto label.

Unlike in Java and C++, the end of a case statement must explicitly state where to go to next. There is no error-prone "default fall through" behavior; not specifying a break results in the next case statement being executed:

void Greet(string title) {
  switch (title) {
    case null:
      Console.WriteLine("And you are?");
      goto default;
    case "King":
      Console.WriteLine("Greetings your highness");
      // error, should specify break, otherwise...
    default :
      Console.WriteLine("How's it hanging?");


2.9.4 Loop Statements

C# enables a sequence of statements to execute repeatedly with the while, do while, for, and foreach statements. while loops
while (Boolean-expr)

 [statement | statement-block]

while loops repeatedly execute a statement block when a boolean expression is true. The expression is tested before the statement block is executed. For example:

int i = 0;
while (i<5) {
  Console.WriteLine (i);
4 do-while loops
 [statement |statement-block]

while (Boolean-expr);

do-while loops differ only in functionality from while loops in that they allow the expression to be tested after the statement block has executed. In this example, a do-while loop prints 8, while a while loop would have not printed anything. For example:

int i = 8;
do {
  Console.WriteLine (i);
while (i<5);
8 for loops
for (statement?; 
 [statement | statement-block]

for loops can be more convenient than while loops when you need to maintain an iterator value. As in Java and C, for loops contain three parts. The first part is a statement executed before the loop begins, and by convention is used to initialize an iterator variable; the second part is a boolean expression that, while true, will execute the statement block, and the third part is a statement executed after each iteration of the statement block, which convention is used to iterate the iterator variable. For example:

for (int i=0; i<10; i++)

Any of the three parts of the for statement may be omitted. One can implement an infinite loop such as the following (though while (true) may be used instead):

for (;;)
  Console.WriteLine("Hell ain't so bad"); foreach loops
foreach ( type-value in IEnumerable )
 [statement | statement-block ]

It is very common for for loops to iterate over a collection, so C#, like Visual Basic, has a foreach statement.

For instance, instead of doing the following:

for (int i=0; i<dynamite.Length; i++)
  Console.WriteLine(dynamite [i]);

You can perform this action:

foreach (Stick stick in dynamite)

The foreach statement works on any collection (including arrays). Although not strictly necessary, all collections leverage this functionality by supporting IEnumerable and IEnumerator, which are explained in Chapter 7. Here is an equivalent way to iterate over our collection:

IEnumerator ie = dynamite.GetEnumerator( );
while (ie.MoveNext( )) {
  Stick stick = (Stick)ie.Current;

Under the hood, the foreach statement also acts as a using statement (covered later in this chapter) on the enumerator object (ie in the example above). In Visual C# 2003, Dispose( ) will be called on the enumerator, even if the enumerator does not implement IEnumerable.

2.9.5 Jump Statements

The C# jump statements are break, continue, goto, return, and throw. All jump statements obey sensible restrictions imposed by try statements (see Section 4.6 in Chapter 4). First, a jump out of a try block always executes the try's finally block before reaching the target of the jump. Second, a jump cannot be made from the inside to the outside of a finally block. The break statement

The break statement transfers execution from the enclosing while loop, for loop, or switch statement block to the next statement block.

int x = 0;
while (true) {
  if (x>5)
    break; // break from the loop
} The continue statement

The continue statement forgoes the remaining statements in the loop and makes an early start on the next iteration.

int x = 0;
int y = 0;
while (y<100) {
  if ((x%7)=  =0)
    continue; // continue with next iteration
} The goto statement
goto statement-label;
goto case-constant;

The goto statement transfers execution to another label within the statement block. A label statement is just a placeholder in a method:

int x = 4;
if (x=  =5)
  goto start;

The goto case statement transfers execution to another case label in a switch block (as explained earlier in the "Switch" section). The return statement
return expr?;

The return statement exits the method, and must return an expression of the method's return type if the method is nonvoid.

int CalcX(int a) {
  int x = a * 100;
  return x; // return to the calling method with value
} The throw statement
throw exception-expr?;

The throw statement throws an exception to indicate an abnormal condition has occurred (see Section 4.6 in Chapter 4).

if (w=  =null)
  throw new ArgumentException("w can't be null"); The lock statement
lock (expr)
 [statement | statement-block]

The lock statement is actually a syntactic shortcut for calling the Enter and Exit methods of the Monitor class (see Chapter 16). The using statement
using (declaration-expr)
 [statement | statement-block]

Many classes encapsulate nonmemory resources, such as file handles, graphics handles, or database connections. These classes implement System.IDisposable, which defines a single parameterless method named Dispose called to clean up these resources. The using statement provides an elegant syntax for declaring and then calling the Dispose method of variables that implement IDisposable. For example:

using (FileStream fs = new FileStream (fileName, FileMode.Open)) {

This is precisely equivalent to:

FileStream fs = new FileStream (fileName, FileMode.Open);
try {
finally {
  if (fs != null)
   ((IDispoable)fs).Dispose( );

For more on IDisposable, see Chapter 15.

    Part II: Programming with the .NET Framework
    Part IV: API Quick Reference