• No results found

Selection and Iteration

In document Dot Net study material (Page 76-84)

C# supports the same selection, iteration, and flow control statements used in C and C++, but generally with some restrictions. These

restrictions are not severe and generally are intended to help you avoid common coding bugs. In this chapter I‘ll discuss statements built around the if, else, switch, case, default, do, while, for, foreach, in, break,

continue, and goto keywords.

Selection Statements

The basic selection statement involves the if and else keywords. The keyword if must be followed by a Boolean expression in parentheses. The statement that follows is executed if the Boolean expression resolves to

true:

if (a < 5) b += 27;

The requirement that the parentheses contain a Boolean expression eliminates a whole class of common C bugs. Almost every C and C++ programmer has committed the common pitfall of mistakenly using an assignment as the test expression when a comparison was intended:

if (a = 5)

The C# compiler flags this statement as an error, and you‘ll probably be thankful it does.

Of course, no compiler can offer full protection against programmer sleepiness. In one early C# program I wrote, I defined a bool variable named trigger, but instead of writing the statement

if (trigger)

for some reason I wanted to be a little more explicit and wanted to type this:

if (trigger == true) Instead, I typed this instead:

if (trigger = true)

If trigger is defined as a bool this is a perfectly valid statement in C# but obviously didn‘t do what I wanted.

If more than one statement should be executed, you can group them as a block of statements in curly brackets:

if (a < 5) {

b += 27; c = 0; }

Some programmers prefer putting the first curly bracket at the end of the line containing the if keyword; that‘s allowed, of course.

The if statement can include an else clause: if (a < 5)

b += 27; else

b -= 7;

Even if the if or else clause is followed by single statements, some programmers prefer enclosing the single statement in curly brackets.

if (a < 5) { b += 27; } else { b -= 7; }

You can nest if statements, and it‘s often common that an else clause consists of nothing but another entire if statement:

if (a < 5) { … } else { if (a > 5) { … } else { … } }

The statements in the second else clause are intended to be executed if a equals 5. Because the if statement inside the first else clause is a single statement, the curly brackets can be removed and the second if keyword can be moved to the same line as the first else, as shown in this common form:

if (a < 5) {

… }

else if (a > 5) { … } else { … }

The curly brackets and the statements within the curly brackets are called a block. (See the C# Language Specification, §8.2) You can declare new variables within the block, but they are only visible within the block and all nested blocks.

You can‘t declare a variable with the same name as one already declared in a parent block, for example:

int A; ... {

int A; // Not allowed! ...

}

The error message on the second declaration is: ―A local variable named ‗A‘ cannot be declared in this scope because it would give a different meaning to ‗A‘, which is already used in a ‗parent or current‘ scope to denote something else.‖ Again, this restriction helps avoid common bugs. However, declaring variables with the same name in sibling blocks is allowed: { int A; ... } ... { int A; // No problem! ... }

The switch and case construction in C# has a restriction not present in C. In C and C++ you can do this:

switch(a) {

case 3: b = 7;

// Fall through isn’t allowed in C# case 4:

c = 3; break;

default: b = 2; c = 4; break; }

In C or C++, in the case where a is equal to 3, one statement is executed and then execution falls through to the case where a is equal to 4. That may be what you intended, or you may have forgotten to type in a break statement. To help you avoid bugs like that, the C# compiler will report an error. C# allows a case to fall through to the next case only when the case contains no statements. This is allowed in C#:

switch (a) { case 3: case 4: b = 7; c = 3; break; default: b = 2; c = 4; break; }

To compensate for the restriction against fall-through, C# allows you to use a goto statement at the end of a case to branch to another case. This is a legal C# implemention of the illegal switch block shown earlier:

switch(a) { case 3: b = 7; goto case 4; case 4: c = 3; break; default: b = 2; c = 4; break; }

You don‘t need the final break at the end of a case if the goto is there instead. You can also branch to the default case:

switch(a) { case 1: b = 2; goto case 3;

case 2: c = 7; goto default; case 3: c = 5; break; default: b = 2; goto case 1; }

The expression in the switch statement must resolve to any integer type,

char, string, or an enumeration, and must match the type in the case

labels.

You can indeed use a string variable in the switch statement and compare it to literal strings in the case statements:

switch (strCity) {

case "Boston": …

break; case "New York": …

break;

case "San Francisco": … break; default: … break; }

Of course, this is exactly the type of thing that causes performance-

obsessed C and C++ programmers to cringe. All those string comparisons simply cannot be very efficient. In fact, because of a technique known as

string interning (which involves a table of all the unique strings used in a

program), it‘s a lot faster than you might think.

Iteration Statements

C# also supports the while statement for repeating a group of statements while a condition is true. You can test a conditional at the top of a block

while (a < 5) {

… }

or at the bottom of a block: do { … } while (a < 5);

As with the if statement, the expression in parentheses must resolve to a

bool. In the second example, the block is executed at least once

regardless of the value of a.

The while or do block can contain a break statement, in which case execution continues with the first statement after the while or do block. The block can also contain a continue statement, which skips the

remainder of the statements and goes back to the top. The for statement looks the same as in C and C++:

for (i = 0; i < 100; i++) {

… }

Within the parentheses, the first part is an initializer that‘s executed before anything in the loop. The second part is a Boolean expression. The contents of the block are executed only if that expression is true. The last part is executed at the end of the block. If A, B, and C are expressions, the statement

for (A; B; C) {

… }

is roughly equivalent to: A; while (B) { … C; }

I say ―roughly‖ because the for block might contain a continue statement to skip the rest of the block and start with the next iteration. However, the C expression will still be executed in that case, whereas it would not in the while statement. The for block can contain a break statement to exit the block.

As in C++, it‘s very common for C# programmers to define the iteration variable right in the for statement:

for (float a = 0; a < 10.5f; a += 0.1f) {

… }

The variable a is only valid within the for statement.

A handy addition to the iteration statements that C# inherited from C and C++ is the foreach statement, which C# picked up from Visual Basic. I‘ll show you some examples of foreach in the Chapter 10, which

discusses arrays. The foreach statement also works with other types of collections, and with strings. Suppose you wanted to display all the characters of a string named str, each on a separate line. With a for loop the code looks like this:

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

The foreach statement is considerably simpler: foreach (char ch in str)

Console.WriteLine(ch);

The parentheses consist of the definition of a variable named ch of type

char; this variable must match the type of the elements in the array or

collection. This is followed by the keyword in followed by the variable containing the elements. You can use break and continue statements within a foreach block.

Within the foreach block, the iteration variable is read-only. This is rather obvious in the case of strings (because strings are enumerable anyway) but in Chapter 10 you‘ll see that you cannot use the foreach statement to initialize the elements of arrays.

The foreach statement requires a collection that supports a particular method, as laboriously described in the C# Language Specification, §8.8.4. In a practical sense, it can be said that the foreach statement works with collections that implement the IEnumerable interface.

Jump Statements

The C# Language Specification, §8.9 defines the category of jump

statements as including break, continue, and return. I‘ll discuss return in more detail in Chapter 11. This category also includes throw, which I‘ll describe in Chapter 12, and finally goto.

You‘ve already seen how to use the goto in a switch statement. You can also use goto to branch to a label. A label is defined with an identifier followed by a colon:

NowhereElseToGo:

You can branch to the statement at that label with the statement goto NowhereElseToGo;

Labels have scopes just like variables, and the label must be in the same block or a parent block as the goto statement. In other words, you can‘t jump into the middle of a block. You can jump out of a block, but not into a block.

In document Dot Net study material (Page 76-84)