Flow Control

 
Chapter 2 - C# Basics
bySimon Robinsonet al.
Wrox Press 2002
  

In this section, we will look at the real nuts and bolts of the language: the statements that allow us to control the flow of our program, rather than executing every line of code in the order it appears in the program.

Conditional Statements

Conditional statements allow us to branch our code depending on whether certain conditions are met or on the value of an expression. C# has two constructs for branching code the if statement, which allows us to test whether a specific condition is met, and the switch statement, which allows us to compare an expression with a number of different values.

The if Statement

For conditional branching, C# inherits C and C++'s if...else construct. The syntax should be fairly intuitive for anyone who has done any programming with a procedural language:

 if (  condition  )  statement(s)  else  statement(s)  

If more than one statement is to be executed as part of either condition, these statements will need to be joined together into a block using curly braces ( { ... } ) (this also applies to other C# constructs where statements can be joined into a block, such as the for and while loops we meet later):

   bool isZero;     if (i == 0)     {     isZero = true;     Console.WriteLine("i is Zero");     }     else     {     isZero = false;     Console.WriteLine("i is Non-zero");     }   

The syntax here is similar to C++ and Java but once again different from VB. VB developers should note that C# does not have any statement corresponding to VB's EndIf . Instead, the rule is that each clause of an if contains just one statement. If you need more than one statement, as in the above example, you should enclose the statements in braces, which will cause the whole group of statements to be treated as a single block statement.

If we want to, we can use an if statement without a final else statement. We can also combine else   if clauses to test for multiple conditions. The following code example is called WhatIsI :

 using System; namespace Wrox.ProCSharp.Basics {    class MainEntryPoint    {       static void Main(string[] args)       {   Console.WriteLine("Type in a string");     string input;     input = Console.ReadLine();     if (input == "")     {     Console.WriteLine("You typed in an empty string");     }     else if (input.Length < 5)     {     Console.WriteLine("The string had less than 5 characters");     }     else if (input.Length < 10)     {     Console.WriteLine("The string had at least 5 but less than 10     characters");     }     Console.WriteLine("The string was " + input);   }    } } 

There is no limit to how many else if 's we can add to an if clause.

You'll notice that in the example above, we declare a string variable called input , get the user to enter text at the command line, feed this into input , and then test the length of this string variable. The code also shows us how easy string manipulation can be in C#. To find the length of input , for example, use input.Length .

One point to note about if is that we don't need to use the braces if there's only one statement in the conditional branch:

   if (i == 0)     Console.WriteLine("i is Zero");       // This will only execute if i == 0     Console.WriteLine("i can be anything");  // Will execute whatever the     // value of i   

However, for consistency, many programmers prefer to use curly braces whenever they use an if statement.

The if statements we have presented also illustrate some of the C# operators that compare values. Note in particular that, like C++ and Java, C# uses == to compare variables for equality. Do not use = for this purpose. A single = is used to assign values.

In C#, the expression in the if clause must evaluate to a Boolean. C++ programmers should be particularly aware of this; unlike C++, it is not possible to test an integer (returned from a function, say) directly. In C#, we have to explicitly convert the integer that is returned to a Boolean true or false , for example by comparing the value with zero or with null :

   if (DoSomething() != 0)     {     // Non-zero value returned     }     else     {     // Returned zero     }   

This restriction is there in order to prevent some common types of run-time bugs that occur in C++. In particular, in C++ it was common to mistype = when == was intended, resulting in unintentional assignments. In C# that will normally result in a compile-time error, since unless you are working with bool values, = will not return a bool .

The switch Statement

The switch...case statement is good for selecting one branch of execution from a set of mutually exclusive ones. It will be familiar to C++ and Java programmers, and is similar to the Select Case statement in VB.

It takes the form of a switch argument followed by a series of case clauses. When the expression in the switch argument evaluates to one of the values beside a case clause, the code immediately following that case clause executes. This is one case where we don't need to use curly braces to join statements into blocks; instead, we mark the end of the code for each case using the break statement. We can also include a default case in the switch statement, which will execute if the expression evaluates to none of the other cases. The following switch statement tests the value of the integerA variable:

   switch (integerA)     {     case 1:     Console.WriteLine("integerA =1");     break;     case 2:     Console.WriteLine("integerA =2");     break;     case 3:     Console.WriteLine("integerA =3");     break;     default:     Console.WriteLine("integerA is not 1,2, or 3");     break;     }   

Note that the case values must be constant expressions variables are not permitted.

Though the switch...case statement should be familiar to C and C++ programmers, C#'s switch...case is a bit safer. Specifically , it prohibits fall-through conditions in almost all cases. This means that if a case clause is fired early on in the block, later clauses cannot be fired unless you use a goto statement to specifically mark that you want them fired too. The compiler enforces this restriction by flagging every case clause that is not equipped with a break statement as an error similar to this:

 Control cannot fall through from one case label ('case 2:') to another 

While it is true that fall-through behavior is desirable in a limited number of situations, in the vast majority of cases it is unintended and results in a logical error that's hard to spot. Isn't it better to code for the norm rather than for the exception?

By getting creative with goto statements (which C# does support) however, you can duplicate fall through functionality in your switch...cases . However, if you find yourself really wanting to, you probably should re-consider your approach. The following code illustrates both how to use goto to simulate fall-through, and how messy the resultant code can get.

   // assume country and language are of type string     switch(country)     {     case "America":     CallAmericanOnlyMethod();     goto case "Britain";     case "France":     language = "French";     break;     case "Britain":     language = "English";     break;     }   

There is one exception to the no-fall-through rule however, in that we can fall through from one case to the next if that case is empty. This allows us to treat two or more cases in an identical way (without the need for goto statements):

   switch(country)     {     case "au":     case "uk":     case "us":     language = "English";     break;     case "at":     case "de":     language = "German";     break;     }   

One intriguing point about the switch statement in C# is that the order of the cases doesn't matter we can even put the default case first! As a result, no two cases can be the same. This includes different constants that have the same value, so we can't, for example, do this:

   // assume country is of type string     const string england = "uk";     const string britain = "uk";     switch(country)     {     case england:     case britain:     language = "English";     break;     }   

The above code also shows another way in which the switch statement is different in C# from C++: In C#, you are allowed to use a string as the variable being tested .

Loops

C# provides four different loops ( for , while , do...while , and foreach ) that allow us to execute a block of code repeatedly until a certain condition is met. The for , while , and do...while loops are essentially identical to those encountered in C++. The for loop is the first that we shall examine.

The for Loop

C# for loops provide a mechanism for iterating through a loop where we test whether a particular condition holds before we perform another iteration. The syntax is:

 for (  initializer;   condition;   iterator  )  statement(s)  

where:

  • The initializer is the expression evaluated before the first loop is executed (usually initializing a local variable as a loop 'counter').

  • The condition is the expression that is checked before each new iteration of the loop (this must evaluate to true for another iteration to be performed).

  • The iterator is an expression that will be evaluated after each iteration (usually incrementing the loop counter). The iterations end when the condition evaluates to false .

The for loop is a so-called pre-test loop , because the loop condition is evaluated before the loop statements are executed, and so the contents of the loop won't be executed at all if the loop condition is false .

The for loop is excellent for repeating a statement or a block of statements for a pre-determined number of times. The following example is typical of the use of a for loop. This code will write out all the integers from 0 to 99:

   for (int i = 0; i < 100; i = i+1)   // this is equivalent to     // For i = 0 To 99 in VB.     {     Console.WriteLine(i);     }   

Here, we declare an int called i and initialize it to zero. This will be used as the loop counter. We then immediately test whether it is less than 100. Since this condition evaluates to true , we execute the code in the loop, displaying the value 0. We then increment the counter by one, and walk through the process again. Looping ends when i reaches 100.

This syntax is far more powerful than the VB For...Next loop, since the iterator can be any statement. In VB, all you can do is add or subtract some number from the loop control variable. In C# you can do anything for example multiply the loop control variable by 2.

It's not unusual to nest for loops so that an inner loop executes once completely for each iteration of an outer loop. This scheme is typically employed to loop through every element in a rectangular multidimensional array. The outermost loop loops through every row, and the inner loop loops through every column in a particular row. The following code is available as the NumberTable sample, and displays rows of numbers . It also uses another Console method, Console.Write() , which does the same as Console.WriteLine() but doesn't send a carriage return to the output.

 using System; namespace Wrox.ProCSharp.Basics {    class MainEntryPoint    {       static void Main(string[] args)       {   // This loop iterates through rows...     for (int i = 0; i < 100; i+=10)     {     // This loop iterates through columns...     for (int j = i; j < i + 10; j++)     {     Console.Write("  " + j);     }     Console.WriteLine();     }   }    } } 

We also see from this sample that strings in C# can be concatenated by using the symbol +:

 Console.Write("  " + j); 

Although j is an integer, it will be automatically converted to a string so that the concatenation can take place. C++ developers will note that this is far easier than string handling ever was in C++, though VB developers will be used to this.

C programmers should take note of one particular feature of the example above. The counter variable in the innermost loop is effectively re-declared with each successive iteration of the outer loop. This syntax is legal not only in C#, but in C++ as well.

The above sample results in this output:

  csc NumberTable.cs  Microsoft (R) Visual C# .NET Compiler version 7.00.9466 for Microsoft (R) .NET Framework version 1.0.3705 Copyright (C) Microsoft Corporation 2001. All rights reserved. NumberTable   0  1  2  3  4  5  6  7  8  9   10  11  12  13  14  15  16  17  18  19   20  21  22  23  24  25  26  27  28  29   30  31  32  33  34  35  36  37  38  39   40  41  42  43  44  45  46  47  48  49   50  51  52  53  54  55  56  57  58  59   60  61  62  63  64  65  66  67  68  69   70  71  72  73  74  75  76  77  78  79   80  81  82  83  84  85  86  87  88  89   90  91  92  93  94  95  96  97  98  99 

Although it is technically possible to evaluate something other than a counter variable in a for loop's test condition, it is certainly not typical. It is also possible to omit one (or even all) of the expressions in the for loop. In such situations however, you should consider using the next type of loop that we will discuss.

The while Loop

The while loop is identical to the while loop in C++ and Java, and the While...Wend loop in VB. Like the for loop, while is a pre-test loop. The syntax is similar, but while loops take only one expression:

   while(condition)     statement(s);   

Unlike the for loop, the while loop is most often used to repeat a statement or a block of a statements for a number of times that is not known before the loop begins. Usually, a statement inside the while loop's body will set a Boolean flag to false on a certain iteration, triggering the end of the loop, as in the following example:

   bool condition = false;     while (!condition)     {     // This loop spins until the condition is true     DoSomeWork();     condition = CheckCondition();   // assume CheckCondition() returns a bool     }   

All of C#'s looping mechanisms, including the while loop, can forego the curly braces that follow them if they intend to repeat just a single statement and not a block of them. Again, many programmers consider it good practice to use braces all of the time.

The dowhile Loop

The do...while loop is the post-test version of the while loop. It does the same thing with the same syntax as do...while in C++ and Java, and the same thing as Loop...While in VB. This means that the loop's test condition is evaluated after the body of the loop has been executed. Consequently, do...while loops are useful for situations in which a block of statements must be executed at least one time, as in this case:

   bool condition;     do     {     // this loop will at least execute once, even if Condition is false     MustBeCalledAtLeastOnce();     condition = CheckCondition();     } while (condition);   

The foreach Loop

The foreach loop is the final C# looping mechanism that we will discuss. While the other looping mechanisms were present in the earliest versions of C and C++, the foreach statement is a new addition (borrowed from VB), and a very welcome one at that.

The foreach loop allows us to iterate through each item in a collection. For the time being we won't worry about exactly what a collection is we'll explain fully in Chapter 5 on C# and Base Classes . For now, we will just say that it is a object that contains other objects. Technically, to count as a collection, it must support an interface called IEnumerable . Examples of collections include C# arrays, the collection classes in the System.Collection namespaces, and user-defined collection classes. We can get an idea of the syntax of foreach from the following code, if we assume that arrayOfInts is (unsurprisingly) an array if int s:

   foreach (int temp in arrayOfInts)     {     Console.WriteLine(temp);     }   

Here, foreach steps through the array one element at a time. With each element, it places the value of the element in the int variable called temp , and then performs an iteration of the loop.

An important point to note with foreach is that we can't change the value of the item in the collection ( temp above), so code such as the following will not compile:

   foreach (int temp in arrayOfInts)     {     temp++;     Console.WriteLine(temp);     }   

If you need to iterate through the items in a collection and change their values, you will need to use a for loop instead.

We will learn how to implement our own collection classes later in this book, in Chapter 5. Interestingly, such classes can be iterated through with Visual Basic .NET's ForEach statement, too.

Jump Statements

C# provides a number of statements that allow us to jump immediately to another line in the program. The first of these is, of course, the notorious goto statement.

The goto Statement

The goto statement allows us to jump directly to another specified line in the program, indicated by a label (this is just an identifier followed by a colon ):

   goto Label1;     Console.WriteLine("This won't be executed");     Label1:     Console.WriteLine("Continuing execution from here");   

There are a couple of restrictions involved with goto . We can't jump into a block of code such as a for loop, we can't jump out of a class, and we can't exit a finally block after try...catch blocks (we will look at exception handling with try...catch...finally in Chapter 4).

The reputation of the goto statement probably precedes it, and in most circumstances, its use is sternly frowned upon. In general, it certainly doesn't conform to good object-oriented programming practice. However, there is one place where it is quite handy: jumping between cases in a switch statement, particularly since C#'s switch is so strict on fall-through. We saw the syntax for this earlier.

The break Statement

We have already met the break statement briefly when we used it to exit from a case in a switch statement. In fact, break can also be used to exit from for , foreach , while , or do...while loops too. Control will switch to the statement immediately after the end of the loop.

If the statement occurs in a nested loop, control will switch to the end of the innermost loop. If the break occurs outside of a switch statement or a loop, a compile-time error will occur.

The continue Statement

The continue statement is similar to break , and must also be used within a for , foreach , while , or do...while loop. However, it exits only from the current iteration of the loop, meaning execution will restart at the beginning of the next iteration of the loop, rather than outside the loop altogether.

The return Statement

The return statement is used to exit a method of a class, returning control to the caller of the method. If the method has a return type, return must return a value of this type; otherwise if the method returns void , then you should use return without an expression. We will look at the syntax for writing and calling methods shortly.

  


Professional C#. 2nd Edition
Performance Consulting: A Practical Guide for HR and Learning Professionals
ISBN: 1576754359
EAN: 2147483647
Year: 2002
Pages: 244

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net