only for RuBoard - do not distribute or recompile |
Execution of 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. The two most basic kinds of statement in C# are the declaration and expression statements. C# also provides flow control statements for selection, looping, and jumping. Finally, C# provides statements for special purposes, such as locking memory or handling exceptions.
So that multiple statements can be grouped together, zero or more statements may be enclosed in braces ({ }) to form a statement block. A statement block can be used anywhere a single statement is valid.
Syntax: |
---|
[variable =]? expression; |
An expression statement evaluates an expression either by assigning its result to a variable or generating side effects, (i.e., invocation, new, ++, or --). 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
Variable declaration syntax: |
---|
type [variable [ = expression ]?]+ ; |
Constant declaration syntax: |
---|
const type [variable = constant-expression]+ ; |
A declaration statement declares a new variable. You can initialize a variable at the time of its declaration by optionally assigning it the result of an expression.
The scope of a local or constant variable extends to the end of the current block. You can't 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 value of the variable can't be changed after it has been declared:
const double speedOfLight = 2.99792458E08; speedOfLight+=10; // error
Syntax: |
---|
; |
The empty statement does nothing. It is used as a placeholder when no operations need to be performed, but a statement is nevertheless required. For example:
while(!thread.IsAlive);
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 a 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.
Syntax: |
---|
if (Boolean-expression) statement-or-statement-block [ else statement-or-statement-block ]? |
An if-else statement executes code depending on whether a Boolean expression is true. Unlike C, C# permits only a Boolean expression. For example:
int Compare(int a, int b) { if (a>b) return 1; else if (a<b) return -1; return 0; }
Syntax: |
---|
switch (expression) { [ case constant-expression : statement* ]* [ default : statement* ]? } |
switch statements let you branch program execution based on the value of a variable. switch statements can result in cleaner code than if you use multiple if statements, because the controlling expression is evaluated only once. For instance:
void Award(int x) { switch(x) { case 1: Console.WriteLine("Winner!"); break; case 2: Console.WriteLine("Runner-up"); break; case 3: case 4: Console.WriteLine("Highly commended"); break; default: Console.WriteLine("Don't quit your day job!"); break; } }
The switch statement can evaluate only a predefined type (including the string type) or enum, though user-defined types may provide an implicit conversion to these types.
After a particular case statement is executed, control doesn't automatically continue to the next statement or break out of the switch statement. Instead, you must explicitly control execution, typically by ending each case statement 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 <constantexpression> or goto default statements to jump to either another case statement or the default case statement.
Use any other jump statement, namely return, throw, continue, or goto label.
Unlike in Java and C++, the end of a case statement must explicitly state where to go next. There is no error-prone "default fall through" behavior, so not specifying a jump statement 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?"); break; } }
C# enables a group of statements to be executed repeatedly using the while, do while, and for statements.
Syntax: |
---|
while (Boolean-expression) statement-or-statement-block |
while loops repeatedly execute a statement block while a given Boolean expression remains true. The expression is tested before the statement block is executed:
int i = 0; while (i<5) { i++; }
Syntax: |
---|
do statement-or-statement-block while (Boolean-expression); |
do-while loops differ functionally from while loops only in that they test the controlling Boolean expression after the statement block has executed. Here's an example:
int i = 0; do i++; while (i<5);
Syntax: |
---|
for (statement?; Boolean-expression?; statement?) statement-or-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, it initializes an iterator variable. The second part is a Boolean expression that, while true, permits the statement block to execute. The third part is a statement that is executed after each iteration of the statement block and, by convention, increments an iterator variable. Here's an example:
for (int i=0; i<10; i++) Console.WriteLine(i);
Any of the three parts of the for statement may be omitted. You can implement an infinite loop like this, though alternatively a while (true) statement has the same result:
for (;;) Console.WriteLine("Hell ain't so bad");
Syntax: |
---|
foreach ( type-value in IEnumerable ) statement-or-statement-block |
It's common to use for loops to iterate over a collection, so C#, like Visual Basic, includes a foreach statement. For instance, instead of doing this:
for (int i=0; i<dynamite.Length; i++) Console.WriteLine(dynamite [i]);
you can do this:
foreach (Stick stick in dynamite) Console.WriteLine(stick);
The foreach statement works on any collection (including arrays). Although not strictly necessary, all collections leverage this functionality by implementing the IEnumerable and IEnumerator interfaces, which are explained in Section 3.4 in Chapter 3. Here is an equivalent way to iterate over the collection:
IEnumerator ie = dynamite.GetEnumerator( ); while (ie.MoveNext( )) { Stick stick = (Stick)ie.Current; Console.WriteLine(stick); }
The C# jump statements are: break, continue, goto, return, and throw. All jump statements obey sensible restrictions imposed by try statements (see Section 2.15 later in this chapter). 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 can't be made from the inside to the outside of a finally block.
Syntax: |
---|
break; |
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) { x++; if (x>5) break; // break from the loop }
Syntax: |
---|
continue; |
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) { x++; if ((x%7)==0) continue; // continue with next iteration y++; }
Syntax: |
---|
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; start: x++; if (x==5) goto start;
The goto case statement transfers execution to another case label in a switch block (as explained in the Section 2.5.4.2 section).
Syntax: |
---|
return expression?; |
The return statement exits a method. If the method is non-void, it must return an expression of the method's return type:
int CalcX(int a) { int x = a * 100; return x; // return to the calling method with value }
Syntax: |
---|
throw exception-expression?; |
The throw statement throws an Exceptionto indicate that an abnormal condition has occurred (see Section 2.15 later in this chapter):
if (w==null) throw new Exception("w can't be null");
Syntax: |
---|
lock (expression) statement-or-statement-block |
The lock statement is actually a syntactic shortcut for calling the Enter and Exit methods of the Monitor class (see Section 3.8 in Chapter 3).
Syntax: |
---|
using (declaration-expression) statement-or-statement-block |
Many classes encapsulate non-memory resources, such as file handles, graphics handles, or database connections. These classes implement System.IDisposable, which defines a single parameterless method named Dispose that is called to clean up these resources. The using statement provides an elegant syntax for declaring, then calling, the Dispose method of variables that implement IDisposable. For example:
using (FileStream fs = new FileStream (fileName, FileMode.Open)) { // do something with fs }
This is precisely equivalent to:
FileStream fs = new FileStream (fileName, FileMode.Open); try { // do something with fs } finally { if (fs != null) ((IDisposable)fs).Dispose( ); }
only for RuBoard - do not distribute or recompile |