Statements

Functions comprise statements that execute sequentially in the textual order in which they appear. A statement block is a series of statements appearing between braces (the {} tokens).

Declaration Statements

A declaration statement declares a new variable, optionally initializing the variable with an expression. A declaration statement ends in a semicolon. You may declare multiple variables of the same type in a comma-separated list. For example:

	string someWord = "rosebud";
	int someNumber = 42;
	bool rich = true, famous = false;

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

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

Local variables

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:

	static void Main()
	{
	  int x;
	  {
	    int y;
	    int x;               // Error, x already defined
	  }
	  {
	    int y;               // OK, y not in scope
	  }
	  Console.WriteLine(y);  // Error, y is out of scope
	}

Expression Statements

Expression statements are expressions that are also valid statements. An expression statement must either change state or call something that might change state. Changing state essentially means changing a variable. The possible expression statements are:

  • Assignment expressions (including increment and decrement expressions)

  • Method call expressions (both void and nonvoid)

  • Object instantiation expressions

Here are some examples:

	// Declare variables with declaration statements:
	string s;
	int x, y;
	System.Text.StringBuilder sb;
	
	// Expression statements
	x = 1 + 2;                 // Assignment expression
	x++;                       // Increment expression
	y = Math.Max (x, 5);       // Assignment expression
	Console.WriteLine (y);     // Method call expression
	sb = new StringBuilder( ); // Assignment expression
	new StringBuilder( );      // Object instantiation
	                           // expression

When you call a constructor or a method that returns a value, you’re not obliged to use the result. However, unless the constructor or method changes state the statement is completely useless:

	new StringBuilder();     // Legal, but does nothing
	new string ('c', 3);     // Legal, but does nothing
	x.Equals (y);            // Legal, but does nothing

Selection Statements

C# has the following mechanisms to conditionally control the flow of program execution:

  • Selection statements (if, switch)

  • Conditional operator (? :)

  • Loop statements (while, do..while, for, foreach)

This section covers the simplest two constructs: the if-else statement and the switch statement.

The if statement

An if statement executes a body of code depending on whether a bool expression is true. For example:

	if (5 < 2 * 3)
	{
	  Console.WriteLine ("true");              // true
	}

If the body of code is a single statement, you can optionally omit the braces:

	if (5 < 2 * 3)
	  Console.WriteLine ("true");             // true

The else clause

An if statement is optionally followed by an else clause:

	if (2 + 2 == 5)
	  Console.WriteLine ("Does not compute");
	else
	  Console.WriteLine ("false");            // false

Within an else clause, you can nest another if statement:

	if (2 + 2 == 5)
	  Console.WriteLine ("Does not compute");
	else
	  if (2 + 2 == 4) Console.WriteLine ("Computes");       // Computes

Changing the flow of execution with braces

An else clause always applies to the immediately preceding if statement in the statement block. For example:

	if (true)
	  if (false)
	    Console.WriteLine( );
	  else
	    Console.WriteLine("executes");

This is semantically identical to:

	if (true)
	{
	  if (false)
	    Console.WriteLine( );
	  else
	    Console.WriteLine("executes");
	}

We can change the execution flow by moving the braces:

	if (true)
	{
	  if (false)
	    Console.WriteLine( );
	}
	else
	  Console.WriteLine("does not execute");

With braces, you explicitly state your intention. This can improve the readability of nested if statements—even when not required by the compiler. A notable exception is with the following pattern:

	static void TellMeWhatICanDo (int age)
	{
	  if (age >= 35)
	    Console.WriteLine ("You can be president!");
	  else if (age >= 21)
	    Console.WriteLine ("You can drink!");
	  else if (age >= 18)
	    Console.WriteLine ("You can vote!");
	  else
	   Console.WriteLine ("You can wait!");
	}

Here, we’ve arranged the if and else statements to mimic the “elsif” construct of other languages (and C#’s #elif preprocessor directive). Visual Studio’s auto-formatting recognizes this pattern and preserves the indentation. Semantically, though, each if statement following an else statement is functionally nested within the else statement.

The switch 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, as switch statements require an expression to be evaluated only once. For instance:

	static void ShowCard (int cardNumber)
	{
	  switch (cardNumber)
	  {
	    case 13:
	      Console.WriteLine ("King");
	      break;
	    case 12:
	      Console.WriteLine ("Queen");
	      break;
	    case 11:
	      Console.WriteLine ("Jack");
	      break;
	    case -1:         // Joker
	     goto case 12;   // Make joker count as queen
	    default:          // Executes for any other cardNumber
	     Console.WriteLine (cardNumber);
	     break;
	  }
	}

You can only switch on an expression of a type that can be statically evaluated, which restricts it to the primitive types, string types, and enum types.

At the end of each case clause, you must say explicitly where execution is to go next, with some kind of jump statement. Here are the options:

  • break (jumps to the end of the switch statement)

  • goto case x (jumps to another case clause)

  • goto default (jumps to the default clause)

  • Any other jump statement—namely, return, throw, continue, or goto label

When more than one value should execute the same code, you can list the common cases sequentially:

	switch (cardNumber)
	{
	  case 13:
	  case 12:
	  case 11:
	    Console.WriteLine ("Face card");break;
	  default:
	    Console.WriteLine ("Plain card");break;
	}

This feature of a switch statement can be pivotal in terms of producing cleaner code than multiple if-else statements.

Iteration Statements

C# enables a sequence of statements to execute repeatedly with the while, do-while, and for statements.

while and do-while loops

while loops repeatedly execute a body of code while a bool expression is true. The expression is tested before the body of the loop is executed. For example:

	int i = 0;
	while (i < 3)
	{
	  Console.Write (i);     // 012
	  i++;
	}

do-while loops differ in functionality from while loops only in that they test the expression after the statement block has executed. Here’s the preceding example rewritten with a do-while loop:

	int i = 0;
	do
	{
	  Console.WriteLine(i);
	  i++;
	}
	while (i < 3);

for loops

for loops are like while loops with special clauses for initialization and iteration of a loop variable. A for loop contains three clauses as follows:

	for (initialization-clause;
	     condition-clause;
	     iteration-clause)statement-or-statement-block
Initialization clause

Executes before the loop begins, used to initialize one or more variables

Condition clause

A bool expression, evaluated before each loop iteration; if false, the loop terminates

Iteration clause

Executes after each iteration of the statement block, used typically to update the loop variable

For example, the following prints the numbers 0 through 2:

	for (int i = 0; i < 3; i++)
	  Console.WriteLine (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("interrupt me");

foreach loops

The foreach statement iterates over each element in an enumerable object. Most of the types in C# and the .NET Framework that represent a set or list of elements are enumerable. For example, both an array and a string are enumerable. Here is an example of enumerating over the characters in a string, from the first character through to the last:

	foreach (char c in "beer")
	  Console.Write (c + " ");        // b e e r

We define enumerable objects in the upcoming “Enumeration and Iterators” section.

Jump Statements

The C# jump statements are break, continue, goto, return, and throw. Jump statements obey the reliability rules of try statements (see the upcoming “try Statements and Exceptions” section). 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 ends the execution of the body of a while loop, for loop, or switch statement:

	int x = 0;
	while (true)
	{
	  if (x++ > 5)
	    break;      // break from the loop
	}
	// execution continues here after break
	...

The continue statement

The continue statement forgoes the remaining statements in the loop and makes an early start on the next iteration. The following loop skips even numbers:

	for (int i = 0; i < 10; i++)
	{
	  if ((i % 2) == 0) continue;
	  Console.Write (i + " ");      // 1 3 5 7 9
	}

The goto statement

The goto statement transfers execution to another label within the statement block. The form is as follows:

	goto statement-label;

or, when used within a switch statement:

	goto case case-constant;

A label statement is just a placeholder in a code block, denoted with a colon suffix. The following example iterates the numbers 1 through 5, mimicking a for loop:

	int i = 1;
	startLoop:
	if (i <= 5)
	{
	  Console.Write (i + " ");    // 1 2 3 4 5
	  i++;
	  goto startLoop;
	}

The goto case statement transfers execution to another case label in a switch block (see the earlier “The switch statement” section).

The return statement

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

	static decimal AsPercentage (decimal d)
	{
	  decimal p = d * 100m;
	  return p;             // Return to the calling method
	                        // with value
	}

A return statement can appear anywhere in a method.

The throw statement

The throw statement throws an exception to indicate an error has occurred (see the upcoming “try Statements and Exceptions” section):

	if (w == null)
	  throw new ArgumentNullException (...);

Miscellaneous Statements

The lock statement is a syntactic shortcut for calling the Enter and Exit methods of the Monitor class, which provide exclusive locking functionality for multithreaded programs. (For an extensive online resource on multithreading, see www.albahari.com/threading/.)

The using statement provides an elegant syntax for declaring a calling Dispose on objects that implement IDisposable (see “try Statements and Exceptions” later in the book).

Note

C# overloads the using keyword to have independent meanings in different contexts. Specifically, the using directive is different from the using statement.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset