Previous section   Next section

3.7 Branching

Visual Basic .NET statements are evaluated in order. The compiler starts at the beginning of a statement list and makes its way to the bottom. This would be entirely straightforward, and terribly limiting, were it not for branching. There are two types of branches in a Visual Basic .NET program: unconditional branching and conditional branching.

Program flow is also affected by looping and iteration statements, which are signaled by the keywords If, Select Case, For, Do, While, and For Each. Iteration is discussed later in this chapter, and For Each is considered in Chapter 3. For now, let's consider some of the more basic methods of conditional and unconditional branching.

3.7.1 Unconditional Branching Statements

An unconditional branch is created by invoking a method. When the compiler encounters the name of a method it stops execution in the current method and branches to the newly "called" method. When that method returns a value, execution picks up in the original method on the line just below the method call. Example 3-4 illustrates.

Example 3-4. Calling a method
Option Strict On
Imports System
Module Module1
   Sub Main( )
      Console.WriteLine("In Main! Calling SomeMethod( )...")
      SomeMethod( )
      Console.WriteLine("Back in Main( ).")
   End Sub 'Main

   Sub SomeMethod( )
      Console.WriteLine("Greetings from SomeMethod!")
   End Sub 'SomeMethod

End Module

Output:
In Main! Calling SomeMethod( )...
Greetings from SomeMethod!
Back in Main( ).

Program flow begins in Main( ) and proceeds until SomeMethod( ) is invoked (invoking a method is sometimes referred to as "calling" the method). At that point program flow branches to the method. When the method completes, program flow resumes at the next line after the call to that method.

You can create an unconditional branch by using one of the unconditional branch keywords: Goto, Exit, Return, or Throw. The first three of these are discussed later in this chapter, while the final statement, Throw, is discussed in Chapter 11.

3.7.2 Conditional Branching Statements

While methods branch unconditionally, often you will want to branch within a method depending on a condition that you evaluate while the program is running. This is known as conditional branching. Conditional branching statements allow you to write logic such as "If you are over 25 years old, then you may rent a car."

VB.NET provides a number of constructs that allow you to write conditional branches into your programs. A conditional branching statement is signaled by keywords such as If and Select Case; these constructs are described in the following sections.

3.7.3 If Statements

The simplest branching statement is If. An If statement says, "If a particular condition is true, then execute the statement; otherwise skip it." (The condition is a Boolean expression. An expression is a statement that evaluates to a value. A Boolean expression evaluates to either true or false.)

The formal description of an If statement is:

If expression Then
   statements
End If

This formal definition states that the If statement takes an expression and Then executes the statements until the End If, but only if the expression evaluates to true.

An alternative one-line version is:

If expression Then statement

Many VB.NET developers avoid the single-line If statement because it can be confusing and thus difficult to maintain.

Example 3-5 illustrates the use of an If statement.

Example 3-5. Using the If statement
Option Strict On
Imports System
Module Module1

   Sub Main( )

      Dim valueOne As Integer = 10
      Dim valueTwo As Integer = 20
      Dim valueThree As Integer = 30

      Console.WriteLine("Testing valueOne against valueTwo...")
      If valueOne > valueTwo Then
         Console.WriteLine( _
             "ValueOne: {0} larger than ValueTwo: {1}", _
              valueOne, valueTwo)
      End If

      Console.WriteLine("Testing valueThree against valueTwo...")
      If valueThree > valueTwo Then
         Console.WriteLine( _
             "ValueThree: {0} larger than ValueTwo: {1}", _
              valueThree, valueTwo)
      End If
      Console.WriteLine("Testing is valueTwo > 15 (one line)...")
      If valueTwo > 15 Then Console.WriteLine("Yes it is")

   End Sub 'Main

End Module
Output:
Testing valueOne against valueTwo...
Testing valueThree against valueTwo...
ValueThree: 30 larger than ValueTwo: 20
Testing is valueTwo > 15 (one line)...
Yes it is

In this simple program, you declare three variables, valueOne, valueTwo, and valueThree, with the values 10, 20, and 30, respectively. In the first If statement, you test whether valueOne is greater than valueTwo:

If valueOne > valueTwo Then
   Console.WriteLine( _
       "ValueOne: {0} larger than ValueTwo: {1}", valueOne, valueTwo)
End If

Because valueOne (10) is less than valueTwo (20), this If statement fails (the condition returns false), and thus the body of the If statement (the statements between the If and the End If) doesn't execute.

The test for greater-than uses the greater-than operator (>), which is discussed in detail later in this chapter.

You then test whether valueThree is greater than valueTwo:

If valueThree > valueTwo Then
   Console.WriteLine( _
       "ValueThree: {0} larger than ValueTwo: {1}", valueThree, valueTwo)
End If

Since valueThree (30) is greater than valueTwo (20), the test returns true, and thus the statement executes. The statement in this case is the call to the WriteLine( ) method, shown in bold in the preceding sample code.

Finally, you use a one-line If statement to test whether valueTwo is greater than 15. Since this evaluates true, the statement that follows executes, and the words "Yes it is" are displayed.

If valueTwo > 15 Then Console.WriteLine("Yes it is")

The output reflects that the first If statement fails, but the second and third succeed:

Testing valueOne against valueTwo...
Testing valueThree against valueTwo...
ValueThree: 30 larger than ValueTwo: 20
Testing is valueTwo > 15 (one line)...
Yes it is

VB6 programmers take note: In Visual Basic .NET, variables created within nested scope (e.g., within an If statement) are scoped to that statement and are not visible outside the nested scope. Thus the following code:

If someValue > someOtherValue Then
    Dim tempValue As Integer = 5
    ' other code here
End If
myValue = tempValue  'error!

will generate a compile error at the last line:

   Name 'tempValue' is not declared

because the variable tempValue was declared within the If statement and thus is not visible outside the If statement.

3.7.4 If . . . Else Statements

Often, you will find that you want to take one set of actions when the condition tests true and a different set of actions when the condition tests false. This allows you to write logic such as, "If you are over 25 years old, then you may rent a car; otherwise, you must take the train."

The otherwise portion of the logic is executed in the Else statement. For example, you can modify Example 3-5 to print an appropriate message whether or not valueOne is greater than valueTwo, as shown in Example 3-6.

Example 3-6. The Else statement
Option Strict On
Imports System
Module Module1

   Sub Main( )

      Dim valueOne As Integer = 10
      Dim valueTwo As Integer = 20
      Dim valueThree As Integer = 30

      Console.WriteLine("Testing valueOne against valueTwo...")
      If valueOne > valueTwo Then
         Console.WriteLine( _
             "ValueOne: {0} larger than ValueTwo: {1}", valueOne, valueTwo)
      Else
         Console.WriteLine( _
            "Nope, ValueOne: {0} is NOT larger than valueTwo: {1}", _
             valueOne, valueTwo)
      End If
   End Sub 'Main

End Module
Output:
Testing valueOne against valueTwo...
Nope, ValueOne: 10 is NOT larger than valueTwo: 20

Because the test in the If statement fails (valueOne is not larger than valueTwo), the body of the If statement is skipped and the body of the Else statement is executed. Had the test succeeded, the If statement body would execute and the Else statement would be skipped.

3.7.5 Nested If Statements

It is possible, and not uncommon, to nest If statements to handle complex conditions. For example, suppose you need to write a program to evaluate the temperature and return the following types of information:

There are many good ways to write this program. Example 3-7 illustrates one approach, using nested If statements.

Example 3-7. Nested If statements
Option Strict On
Imports System
Module Module1


   Sub Main( )
      Dim temp As Integer = 32

      If temp <= 32 Then
         Console.WriteLine("Warning! Ice on road!")
         If temp = 32 Then
            Console.WriteLine("Temp exactly freezing, beware of water.")
         Else
            Console.WriteLine("Watch for black ice! Temp: {0}", temp)
         End If 'temp = 32
      End If 'temp <= 32
   End Sub 'Main 

End Module
Output:
Warning! Ice on road!
Temp exactly freezing, beware of water.

The logic of Example 3-7 is that it tests whether the temperature is less than or equal to 32. If so, it prints a warning:

If temp <= 32 Then
         Console.WriteLine("Warning! Ice on road!")

The program then uses a second If statement, nested within the first, to check whether the temp is equal to 32 degrees. If so, it prints one message ("Temp exactly freezing, beware of water."); if not, the temp must be less than 32 and an Else is executed, causing the program to print the next message ("Watch for black ice . . ."). Because the second If statement is nested within the first If, the logic of the Else statement is: "Since it has been established that the temp is less than or equal to 32, and it isn't equal to 32, it must be less than 32."

The less-than-or-equal-to operator <= is described under Section 3.9.3, later in this chapter.

3.7.6 ElseIf

The ElseIf statement allows you to perform a related sequence of Ifs. The logic of ElseIf is that if the first If evaluates false, then evaluate the first ElseIf. The first If/ElseIf statement to evaluate true will have its statements executed (and no others will even be evaluated). If none of the statements evaluates true, the final Else clause is executed. Example 3-8 uses ElseIf to perform the same actions as Example 3-7.

Example 3-8. The ElseIf statement
Option Strict On
Imports System
Module Module1

   Sub Main( )
      Dim temp As Integer = -32

      If temp > 32 Then
         Console.WriteLine("Safe driving...")
      ElseIf temp = 32 Then
         Console.WriteLine("Warning, 32 degrees, watch for ice and water")
      ElseIf temp > 0 Then
         Console.WriteLine("Watch for ice...")
      ElseIf temp = 0 Then
         Console.WriteLine("Temperature = 0")
      Else
         Console.WriteLine("Temperatures below zero, Wicked Cold!")
      End If
   End Sub 'Main 

End Module
Output:
Temperatures below zero, Wicked Cold!

3.7.7 IIF: If and Only IF

A very common idiom is to test an expression and to assign a value to a variable based on the result of that test. For example, you might want to find the larger of two values. You can certainly do so with an If...Else statement, as shown in Example 3-9.

Example 3-9. Set max value with If...Else
Option Strict On
Imports System
Module Module1

    Sub Main( )

        Dim valueOne As Integer = 10
        Dim valueTwo As Integer = 20
        Dim maxValue As Integer

        If valueOne > valueTwo Then
            maxValue = valueOne
        Else
            maxValue = valueTwo
        End If

        Console.WriteLine("ValueOne: {0}, valueTwo: {1},  maxValue: {2}", _
          valueOne, valueTwo, maxValue)
    End Sub 'Main

End Module
Output:
ValueOne: 10, valueTwo: 20,  maxValue: 20

Because If...Else is such a common task, however, Visual Basic .NET provides a special keyword, IIF, to test an expression and return one of two values. (The letters that make up the keyword are meant to suggest "If and only IF" and that is also the way you should read the keyword.) The IIF statement takes three arguments:

The logic of an IIF statement is this: If valueOne is greater than valueTwo, return the value in valueOne and assign it to maxValue, otherwise return the value in valueTwo and assign that to maxValue.

Thus, you can rewrite Example 3-9, eliminating the If...Else block with a single IIF statement, as shown in Example 3-10.

Example 3-10. The IIF statement
Option Strict On
Imports System
Module Module1

    Sub Main( )

        Dim valueOne As Integer = 10
        Dim valueTwo As Integer = 20
        Dim maxValue As Integer

        maxValue = CInt(IIf((valueOne > valueTwo), valueOne, valueTwo))

        Console.WriteLine("ValueOne: {0}, valueTwo: {1},  maxValue: {2}", _
          valueOne, valueTwo, maxValue)
    End Sub 'Main

End Module

The IIF statement is defined to take a Boolean expression and two objects and return an object. Thus, the return value must be cast to an Integer.

3.7.8 Select Case Statements

Nested If statements and long sequences of ElseIf statements are hard to read, hard to get right, and hard to debug. When you have a complex set of choices to make, the Select Case statement is a more powerful alternative. The logic of a Select Case statement is this: "Pick a matching value and act accordingly." The syntax is as follows:

Select [ Case ] testExpression
[ Case expressionList
   [ statements ] ]
[ Case Else 
   [ else-statements] ]
End Select

It is easiest to understand this construct in the context of a sample program. In Example 3-11, a value of 15 is assigned to the variable targetInteger. The Select Case statement tests for the values 5, 10, and 15. If one matches, the associated statement is executed.

Example 3-11. Using Select Case
Option Strict On
Imports System
Module Module1

   Sub Main( )
      Dim targetInteger As Integer = 15

      Select targetInteger
         Case 5
            Console.WriteLine("5")
         Case 10
            Console.WriteLine("10")
         Case 15
            Console.WriteLine("15!")
         Case Else
            Console.WriteLine("Value not found")
      End Select
   End Sub 'Main 

End Module 

Output:
15!

The output shows that 15 matched, and the associated statement was executed, displaying the value "15!". If none of the values matched, any statements following Case Else would be executed.

Note that Case also allows you to check a variable against a range of values. You can combine Case with the keywords Is and To to specify the ranges, as illustrated in Example 3-12. Note that the target value (targetInteger) has been changed to 7.

Example 3-12. Testing for a range of values
Option Strict On
Imports System

Module Module1

   Sub Main( )
      Dim targetInteger As Integer = 7

      Select Case targetInteger
         Case Is < 10
            Console.WriteLine("Less than 10")
         Case 10 To 14
            Console.WriteLine("10-14")
         Case 15
            Console.WriteLine("15!")
         Case Else
            Console.WriteLine("Value not found")
      End Select
   End Sub 'Main 

End Module

Output:
Less than 10

In Example 3-12, the first test examines whether targetInteger is less than 10. You specify this by combining Case with the Is keyword followed by the less-than operator and the number 10 to specify the range:

Case Is < 10

You then use Case with the To keyword to specify a range of 10 through 14:

Case 10 To 14

The preceding Case will match any value of 10 through 14, inclusive.

You are not restricted to just testing for a numeric value. You can also test for String values. In fact, you can test ranges of String values, examining whether a target value fits alphabetically within the range, as shown in Example 3-13.

Example 3-13. Testing alphabetic ranges
Option Strict On
Imports System
Module Module1

   Sub Main( )

      Dim target As String = "Milo"

      Select Case target
 
         Case "Alpha" To "Lambda "
            Console.WriteLine("Alpha To Lambda executed")
         Case "Lamda" To "Zeta"
            Console.WriteLine("Lambda To Zeta executed")
         Case Else
            Console.WriteLine("Else executed")
      End Select
   End Sub 'Main 

End Module

Output:
Lambda To Zeta executed

Example 3-13 tests whether the string "Milo" fits within the alphabetic range between the strings "Alpha" and "Lambda"; then it tests whether "Milo" fits within the range between the strings "Lambda" and "Zeta." Both ranges are inclusive. Clearly the second range encompasses the string "Milo" and the output bears that out.

You can also simply test whether one string matches another. The following case tests whether the string "Milo" is the same as the string "Fred":

Dim target As String = "Milo"

Select Case target
    Case "Fred"
        Console.WriteLine("Fred") 

But clearly "Milo" does not equal "Fred."

You can also combine a series of tests in a single Case statement, separating them by commas. Thus you could test whether "Milo" matches either of the strings "Fred" or "Joe" and also whether it falls within the (admittedly small) alphabetic range that comes before "Alpha" using the following code:

Dim target As String = "Milo"

Select Case target
    Case "Fred", "Joe", Is < "Alpha"
       Console.WriteLine("Joe or Fred or < Alpha")

Clearly "Milo" would not match any of these cases; but changing the target string to "Aardvark" would get you somewhere.


  Previous section   Next section
Top