Branching


Branching is the act of controlling which line of code should be executed next. The line to jump to is controlled by some kind of conditional statement. This conditional statement will be based on a comparison between a test value and one or more possible values using Boolean logic.

In this section, you will look at the three branching techniques available in C#:

  • The ternary operator

  • The if statement

  • The switch statement

The Ternary Operator

The simplest way of performing a comparison is to use the ternary (or conditional) operator mentioned in the last chapter. You've already seen unary operators that work on one operand, and binary operators that work on two operands, so it may come as no surprise that this operator works on three operands. The syntax is as follows:

 <test> ? <resultIfTrue> : <resultIfFalse> 

Here, <test> is evaluated to obtain a Boolean value, and the result of the operator is either <resultIfTrue> or <resultIfFalse> based on this value.

You might use this as follows:

 string resultString = (myInteger < 10) ? "Less than 10" : "Greater than or equal to 10"; 

Here, the result of the ternary operator is one of two strings, both of which may be assigned to resultString. The choice of which string to assign is made by comparing the value of myInteger to 10, where a value of less than 10 results in the first string being assigned, and a value of greater than or equal to 10 the second string. For example, if myInteger is 4 then resultString will be assigned the string Less than 10.

This operator is fine for simple assignments such as this, but isn't really suitable for executing larger amounts of code based on a comparison. A much better way of doing this is to use the if statement.

The if Statement

The if statement is a far more versatile and useful way of making decisions. Unlike ?: statements, if statements don't have a result (so you can't use them in assignments); instead you use the statement to conditionally execute other statements.

The simplest use of an if statement is as follows:

 if (<test>)    <code executed if <test> is true>; 

Where <test> is evaluated (it must evaluate to a Boolean value for the code to compile) and the line of code that follows the statement is executed if <test> evaluates to true. After this code is executed, or if it isn't executed due to <test> evaluating to false, program execution resumes at the next line of code.

You can also specify additional code using the else statement in combination with an if statement. This statement will be executed if <test> evaluate to false:

if (<test>)    <code executed if <test>  is true>;     else    <code executed if <test>  is false>; 

Both sections of code can span multiple lines using blocks in braces:

if (<test>) {    <code executed if <test>  is true>; } else {    <code executed if <test> is false>; } 

As a quick example, you could rewrite the code from the last section that used the ternary operator:

string resultString = (myInteger < 10) ? "Less than 10"                                        : "Greater than or equal to 10";

Since the result of the if statement cannot be assigned to a variable, you have to assign a value to the variable in a separate step:

 string resultString; if (myInteger < 10) resultString = "Less than 10"; else resultString = "Greater than or equal to 10"; 

Code such as this, although more verbose, is far easier to read and understand than the equivalent ternary form, and allows far more flexibility.

Try It Out – Using the if Statement

image from book
  1. Create a new console application called Ch04Ex02 in the directory C:\BegVCSharp\Chapter4.

  2. Add the following code to Program.cs:

    static void Main(string[] args) { string comparison; Console.WriteLine("Enter a number:"); double var1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("Enter another number:"); double var2 = Convert.ToDouble(Console.ReadLine()); if (var1 < var2) comparison = "less than"; else { if (var1 == var2) comparison = "equal to"; else comparison = "greater than"; } Console.WriteLine("The first number is {0} the second number.", comparison); Console.ReadKey(); }

  3. Execute the code, and enter two numbers at the prompts, as shown in Figure 4-2.

    image from book
    Figure 4-2

How It Works

The first section of code is familiar and simply obtains two double values from user input:

string comparison; Console.WriteLine("Enter a number:"); double var1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("Enter another number:"); double var2 = Convert.ToDouble(Console.ReadLine());

Next, you assign a string to the string variable comparison based on the values obtained for var1 and var2. First, you check to see if var1 is less than var2:

if (var1 < var2)    comparison = "less than";

If this isn't the case, then var1 is either greater than or equal to var2. In the else section of the first comparison, you need to nest a second comparison:

else {    if (var1 == var2)       comparison = "equal to";

The else section of this second comparison will only be reached if var1 is greater than var2:

   else       comparison = "greater than"; }

Finally, you write the value of comparison to the console:

Console.WriteLine("The first number is {0} the second number.",                   comparison);

The nesting you have used here is just one way of doing things. You could equally have written:

 if (var1 < var2) comparison = "less than"; if (var1 == var2) comparison = "equal to"; if (var1 > var2) comparison = "greater than"; 

The disadvantage with this method is that you are performing three comparisons regardless of the values of var1 and var2. With the first method, you only perform one comparison if var1 < var2 is true and two comparisons otherwise (you also perform the var1 == var2 comparison), resulting in fewer lines of code being executed. The difference in performance here will be slight, but would be significant in applications where speed of execution is crucial.

image from book

Checking More Conditions Using if Statements

In the preceding example, you checked for three conditions involving the value of var1. This covered all possible values for this variable. At other times, you might want to check for specific values, say if var1 is equal to 1, 2, 3, or 4, and so on. Using code such as that above can result in annoyingly nested code, for example:

 if (var1 == 1) { // Do something. } else { if (var1 == 2) { // Do something else. } else { if (var1 == 3 || var1 == 4) { // Do something else. } else { // Do something else. } } } 
Note

Note that it is a common mistake to write conditions such as the third condition as if (var1 == 3 || 4). Here, owing to operator precedence, the == operator is processed first, leaving the || operator to operate on a Boolean and a numeric operand. This will cause an error.

In these situations, it can be worth using a slightly different indentation scheme and contracting the block of code for the else blocks (that is, using a single line of code after the else blocks rather than a block of code). When you do this, you end up with a structure involving else if statements:

 if (var1 == 1) { // Do something. } else if (var1 == 2) { // Do something else. } else if (var1 == 3 || var1 == 4) { // Do something else. } else { // Do something else. } 

These else if statements are really two separate statements, and the code is functionally identical to the above code. However, this code is much easier to read.

When making multiple comparisons such as this, it can be worth considering the switch statement as an alternative branching structure.

The switch Statement

The switch statement is very similar to the if statement in that it executes code conditionally based on the value of a test. However, switch allows you to test for multiple values of a test variable in one go, rather than just a single condition. This test is limited to discrete values, rather than clauses such as "greater than X," so its use is slightly different, but it can be a powerful technique.

The basic structure of a switch statement is:

 switch (<testVar>) {    case <comparisonVal1>:       <code to execute if <testVar>  == <comparisonVal1>> break;    case <comparisonVal2>:       <code to execute if <testVar>  == <comparisonVal2> > break; ...    case <comparisonValN>:       <code to execute if <testVar>  == <comparisonValN> > break; default:       <code to execute if <testVar>  != comparisonVals> break; } 

The value in <testVar> is compared to each of the <comparisonValX> values (specified with case statements), and if there is a match, then the code supplied for this match is executed. If there is no match, then the code in the default section is executed if this block exists.

On completion of the code in each section, you have an additional command, break. It is illegal for the flow of execution to reach a second case statement after processing one case block.

Note

Note that this behavior is one area where C# differs from C++, where the processing of case statements is allowed to run from one to another.

The break statement here simply terminates the switch statement, and processing continues on the statement following the structure.

There are alternative methods of preventing flow from one case statement to the next in C# code. You can use the return statement, which results in termination of the current function rather than just the switch structure (see Chapter 6 for more details about this), or a goto statement. goto statements (as detailed earlier) work here, since case statements in effect define labels in C# code. For example:

switch (<testVar>) {    case <comparisonVal1>:       <code to execute if <testVar>  == <comparisonVal1> >     goto case <comparisonVal2>;    case <comparisonVal2>:       <code to execute if <testVar>  == <comparisonVal2> >       break;    ...

There is one exception to the rule that the processing of one case statement can't run freely into the next. If you place multiple case statements together (stack them) before a single block of code, you are in effect checking for multiple conditions at once. If any of these conditions is met the code is executed, for example:

switch (<testVar>) {        case  <comparisonVal1>:    case  <comparisonVal2>:           <code to execute if <testVar>  == <comparisonVal1>  or                           <testVar>  == <comparisonVal2>  >       break;    ...

Note that these conditions also apply to the default statement. There is no rule saying that this statement must be the last in the list of comparisons, and you can stack it with case statements if you wish. Adding a break point with break, goto, or return ensures that a valid execution path exists through the structure in all cases.

Each of the <comparisonValX> comparisons must be a constant value. One way of doing this is to provide literal values, for example:

 switch (myInteger) { case 1:       <code to execute if myInteger == 1 > break; case -1:       <code to execute if myInteger == -1 > break; default:       <code to execute if myInteger != comparisons> break; } 

Another way is to use constant variables. Constant variables (also known as just "constants," avoiding the oxymoron) are just like any other variable, except for one key factor: the value they contain never changes. Once you assign a value to a constant variable, that is the value it will have for the duration of code execution. Constant variables can come in handy here, because it is often easier to read code where the actual values being compared are hidden from you at the time of comparison.

You declare constant variables using the const keyword in addition to the variable type, and you must assign them values at this time, for example:

 const int intTwo = 2; 

This code is perfectly valid, but if you try

 const int intTwo; intTwo = 2; 

you will get an error and won't be able to compile your code. This also happens if you try to change the value of a constant variable through any other means after initial assignment.

In the following Try It Out, you use a switch statement to write different strings to the console, depending on the value you enter for a test string.

Try It Out – Using the switch Statement

image from book
  1. Create a new console application called Ch04Ex03 in the directory C:\BegVCSharp\Chapter4.

  2. Add the following code to Program.cs:

    static void Main(string[] args) { const string myName = "karli"; const string sexyName = "angelina"; const string sillyName = "ploppy"; string name; Console.WriteLine("What is your name?"); name = Console.ReadLine(); switch (name.ToLower()) { case myName: Console.WriteLine("You have the same name as me!"); break;  case sexyName: Console.WriteLine("My, what a sexy name you have!"); break; case sillyName: Console.WriteLine("That's break; } Console.WriteLine("Hello {0}!", name); Console.ReadKey(); }

  3. Execute the code and enter a name. The result is shown in Figure 4-3.

    image from book
    Figure 4-3

How It Works

The code sets up three constant strings, accepts a string from the user, and then writes out text to the console based on the string entered. In this case the strings are names.

When you compare the name entered (in the variable name) to your constant values, you first force it into lowercase with name.ToLower(). This is a standard command that will work with all string variables, and it comes in handy when you're not sure what has been entered by the user. Using this technique the strings Karli, kArLi, karli, and so on will all match the test string karli.

The switch statement itself attempts to match the string entered with the constant values you have defined and writes out a personalized message, if successful, to greet the user. If no match is made, you simply greet the user.

switch statements have no limit on the amount of case: sections they contain, so you could extend this code to cover every name you can think of should you wish . . . but it might take a while!

image from book




Beginning Visual C# 2005
Beginning Visual C#supAND#174;/sup 2005
ISBN: B000N7ETVG
EAN: N/A
Year: 2005
Pages: 278

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