Looping Statements


Looping statements make the program execute a series of statements repeatedly. The loop can run for a fixed number of repetitions, run while some condition holds true, or run until some condition is true.

Broadly speaking, there are two types of looping statement. For loops execute a certain number of times that (in theory at least) is known. For example, a For loop may execute a series of statement exactly 10 times. Or, it may execute the statements once for each object in a certain collection. If you know how many items are in the collection, you can calculate the number of times the loop will execute.

A While loop executes while a condition is true or until a condition is met. Without a lot more information about the application, it is impossible to tell how many times the code will execute. For example, suppose that a program looks through a list of employees until it finds one who is a manager. Even if you know the number of employees in the list and the number who are managers, you cannot easily tell how many records you will need to search before you find a manager.

The following sections describe the looping statements supported by Visual Basic .NET. The next two sections describe For loops, and the sections after those describe While loops.

For Next

The For Next loop is the most common type of looping statement in Visual Basic. The syntax is as follows:

  For variable [As data_type] = start_value To stop_value [Step increment]     statements     [Exit For]     statements     [Continue For]     statements Next [variable] 

The value variable is the looping variable that controls the loop. When the program reaches the For statement, it sets variable equal to start_value. It then compares variable to stop_value. If variable has passed stop_value, the loop exits. This is important. It means the loop may not execute even once depending on the start and stop values.

Normally, you would not intentionally write a loop that doesn’t execute, but this can occur when you use variables for the start and stop values. For example, the following loop runs for the values employee_num =1, employee_num = 2, . . . , employee_num = num_employees. If the program has not loaded any employees so num_employees = 0, the code inside the loop is not executed at all.

  For employee_num = 1 To num_employees     ProcessEmployee(employee_num) Next employee_num 

After it compares variable to stop_value, the program executes the statements inside the loop. It then adds increment to variable and starts the process over, again comparing variable to stop_value. If you omit increment, the program uses an increment of 1.

Note that increment can be negative or a fractional number, as in the following example:

  For i As Integer = 3 To 1 Step -0.5     Debug.WriteLine(i) Next i 

If increment is positive, the program executes as long as variable <= stop_value. If increment is negative, the program executes as long as variable >= stop_value. This means that the loop would not execute infinitely if increment were to move variable away from stop_value. For example, in the following code start_value = 1 and increment = -1. The variable i would take the values i=1, i=0, i=-1, and so forth, so i will never reach the stop_value of 2. However, because increment is negative, the loop only executes while i>=2. Because i starts with the value 1, the program immediately exits and the loop doesn’t execute at all.

  For i As Integer = 1 To 2 Step -1     Debug.WriteLine(i) Next i 

The program doesn’t need for you to include the variable’s name in the Next statement, although including the name helps make the code easier to read. If you specify the name in the Next statement, it must match the name you use in the For statement.

If you do not specify the looping variable’s data type in the For statement and you have Option Explicit turned on, you must declare the variable before the loop. For example, the following loop declares the variable i outside of the loop:

  Dim i As Integer For i = 1 To 10     Debug.WriteLine(i) Next i 

You cannot declare the same variable both inside and outside of a loop. If you declare a variable in the For statement, the variable’s scope is limited to the loop, and code outside of the loop cannot access the variable.

Declaring the variable in the For statement is a good practice. It limits the scope of the variable so you don’t need to remember what the variable is for in other pieces of code. It keeps the variable’s declaration close to the code where it is used, so it’s easier to remember the variable’s data type. It also lets you more easily reuse counter variables without fear of confusion. If you have several loops that need an arbitrarily named looping variable, they can all declare and use the variable i without interfering with each other.

The program calculates its start_value and stop_value before the loop begins and it never recalculates them, even if their values change. For example, the following code loops from 1 to this_customer.Orders(1).NumItems. The program calculates this_customer.Orders(1).NumItems before executing the loop and doesn’t recalculate that value even if it later changes. This saves the program time, particularly for long expressions such as this one, which could take a noticeable amount of time to reevaluate each time through a long loop.

  For item_num As Integer = 1 To this_customer.Orders(1).NumItems     this_customer.ProcessItem(item_num) Next item_num 

If you must reevaluate stop_value every time the loop executes, use a While loop.

The Exit For statement allows the program to leave a For loop before it would normally finish. For example, the following code loops through the employees array. When it finds an entry with the IsManager property set to True, it saves the employee’s index and uses Exit For to immediately stop looping.

  Dim manager_index As Integer For i As Integer = employees.GetLowerBound(0) To _                    employees.GetUpperBound(0)     If employees(i).IsManager Then         manager_index = i         Exit For     End If Next i  

The Exit For statement exits only the For loop immediately surrounding the statement. For example, in the following code, variable i loops from 1 to 5. Within that loop, variable j loops from 1 to 5. If the two values are equal, the Exit For statement ends the inner loop, but the outer loop continues.

  For i As Integer = 1 To 5     For j As Integer = 1 To 5         If i = j Then Exit For         Debug.WriteLine("(" & i & ", " & j & ")")     Next j Next i  

The following shows this code’s result. You may want to walk through the code either mentally or in the debugger to convince yourself that this makes sense.

  (2, 1) (3, 1) (3, 2) (4, 1) (4, 2) (4, 3) (5, 1) (5, 2) (5, 3) (5, 4) 

The Continue For statement makes the loop jump back to its For statement, increment its looping variable, and start the loop over again. This is particularly useful if the program doesn’t need to execute the rest of the steps within the loop and wants to quickly start the next iteration.

Your code can change the value of the control variable inside the loop, but that’s generally not a good idea. The For Next loop has a very specific intent, and modifying the control variable inside the loop violates that intent, making the code more difficult to understand and debug. If you must modify the control variable in more complicated ways than are provided by a For Next loop, use a While loop instead. Then programmers reading the code won’t expect a simple incrementing loop.

Non-integer For Next Loops

Usually a For Next loop’s control variable is an integral data type such as an Integer or Long, but it can be any of the fundamental Visual Basic numeric data types. For example, the following code uses a variable declared as Single to display the values 1.0, 1.5, 2.0, 2.5, and 3.0:

  For x As Single = 1 To 3 Step 0.5     Debug.WriteLine(x.ToString("0.0")) Next x 

Because floating-point numbers cannot exactly represent every possible value, however, these data types are subject to rounding errors that can lead to unexpected results in For Next loops. The previous code works as you would expect, at least on my computer. The following code, however, has problems. Ideally, this code would display values between 1 and 2, incrementing them by 1/7. Because of rounding errors, however, the value of x after seven trips through the loop is approximately 1.85714316. The program adds 1/7 to this and gets 2.0000003065381731. This is greater than the stopping value 2, so the program exits the loop and the Debug statement does not execute for x = 2.

  For x As Single = 1 To 2 Step 1 / 7     Debug.WriteLine(x) Next x 

One solution to this type of problem is to convert the code into a loop that uses an Integer control variable. Integer variables do not have the same problems with rounding errors that floating-point numbers do, so you have more precise control over the values used in the loop.

The following code does roughly the same thing as the previous code. It uses an Integer control variable, however, so this loop executes exactly eight times as desired. The final value printed into the Output window by the program is 2.

  Dim x As Single x = 1 For i As Integer = 1 To 8     Debug.WriteLine(x)     x += CSng(1 / 7) Next i 

If you look at the value of variable x in the debugger, you will find that its real value during the last trip through the loop is roughly 2.0000001702989851. If this variable were controlling the For loop, the program would see that this value is greater than 2, so it would not display its final value.

For Each

A For Each loop iterates over the items in a collection, array, or other container class that supports For Each loops. The syntax is as follows:

  For Each variable [As object_type] In group     statements     [Exit For]     statements     [Continue For]     statements Next [variable] 

Here, group is a collection, array, or other object that supports For Each. As in For Next loops, the control variable must be declared either in or before the For statement.

To support For Each, the group object must implement the System.Collections.IEnumerable interface. This interface defines a GetEnumerator method that returns an enumerator. For more information, see the next section, “Enumerators.”

The control variable must be of a data type compatible with the objects contained in the group. If the group contains Employee objects, the variable could be an Employee object. It could also be a generic Object or any other class that readily converts into an Employee object. For example, if Employee inherits from the Person class, then the variable could be of type Person.

Visual Basic doesn’t automatically understand what kinds of objects are stored in a collection or array until it tries to use them. If the control variable’s type is not compatible with an object’s type, the program generates an error when the For Each loop tries to assign the control variable to that object’s value.

For example, the following code creates a collection containing an Employee object and a Customer object. It then uses a For Each loop to display the name of each object. The control variable emp is of type Employee. The first time through the loop, the program sets emp equal to the collection’s Employee object and displays its name as expected. The second time through the loop, the program tries to set emp equal to the collection’s Customer object. That causes an “invalid cast exception.”

  Dim people As New Collection people.Add(New Employee("Alice Auxley")) people.Add(New Customer("Bob Brentwood")) For Each emp As Employee In people     Debug.WriteLine(emp.Name) Next emp 

When a collection or array contains more than one type of object (as in the previous example), the control variable must be of a type that can hold all of the objects. Assuming that the Employee and Customer classes in the previous example are not derived from a common ancestor class, the code must use a control variable of type Object, as in the following code:

  For Each person As Object In people     Debug.WriteLine(person.Name) Next person 

This code works as long as the Employee and Customer classes both have a Name property. However, if you have set Option Strict On, the compiler will complain because the generic Object class does not have a Name method. To avoid this error, you need to convert the generic Object variable into a specific type that does have the Name method.

The following code shows one way to use specific object types. The program uses the TypeOf statement to check the control variable’s class type. If the object has type Employee, then the code uses CType to convert the Object variable into an Employee object. It then uses that object’s Name method. Similarly, if the object is a Customer, the code uses CType to convert the generic Object into a Customer and uses its

  Name method. Dim emp As Employee For Each person As Object In people     If TypeOf person Is Employee Then         emp = CType(person, Employee)         Debug.WriteLine(emp.Name)     ElseIf TypeOf person Is Customer Then         Debug.WriteLine(CType(person, Customer).Name)     End If Next person 

You can use the Exit For statement to jump out of a For Each loop early. The following code loops through the employees collection using TypeOf to examine each object’s type. When it finds an object that has type Manager, the code saves a reference to the Manager object and uses Exit For to stop looping.

  Dim a_manager As Manager For Each emp As Employee in employees     If TypeOf emp Is Manager Then         a_manager = CType(emp, Manager)         Exit For     End If Next emp 

The Continue For statement makes the loop jump back to its For statement, fetch the next object from the collection, and start the loop over again. This is particularly useful if the program doesn’t need to execute the rest of the steps within the loop and wants to quickly start the next iteration.

You should not rely on the value of the looping variable outside of the loop, even if you declare the variable before the loop begins. After the loop ends in the current version of Visual Basic .NET, the variable contains a reference to the last object the code processed. If the code uses an Exit For statement, the variable refers to whatever object the code was processing at the time. If the loop examines all the objects in the group and finishes normally, the variable refers to the last object in the collection.

This behavior is different from previous versions of Visual Basic, however. In Visual Basic 6, the looping variable is set to Nothing if the loop examines all the collection’s objects and finishes normally.

To avoid confusion and possibly subtle bugs in future versions of Visual Basic, do not use the control variable outside of the loop. If you must use one of the objects in the collection later, save a reference to it in a variable declared outside of the loop, as shown in the previous example.

You cannot declare the same variable both inside and outside of a For Each loop. If you declare a variable in the For Each statement, the variable’s scope is limited to the loop, and code outside of the loop cannot access the variable.

Declaring the variable in the For Each statement is a good practice. It limits the scope of the variable, so you don’t need to remember what the variable is for in other pieces of code. It keeps the variable’s declaration close to the code where it is used, so it’s easier to remember the variable’s data type. It also lets you more easily reuse counter variables without fear of confusion. If you have several loops that need an arbitrarily named looping variable, they can all declare and use the variable obj, person, or whatever else makes sense without interfering with each other.

Your code can change the value of the control variable inside the loop, but that has no effect on the loop’s progress through the collection or array. The loop resets the variable to the next object inside the group and continues as if you had never changed the variable’s value.

To avoid confusion, you should not change the control variable’s value, because that may lead other programmers to believe that you are trying to change the way the loop works through the group of objects. If you must do something more elaborate with an object, assign the control variable to a temporary variable and work with that instead. If you need to move arbitrarily through the group, consider using a While loop instead of a For Each loop.

Changes to a collection are immediately reflected in the loop. For example, if the statements inside the loop add a new object to the end of the collection, then the loop continues until it processes the new item. Similarly if the loop’s code removes an item from the end of the collection (that it has not yet reached), the loop does not process that item.

The exact effect on the loop depends on whether the item added or removed comes before or after the object the loop is currently processing. For example, if you remove an item before the current item, the loop has already examined that item, so there is no change to the loop. If you remove an item after the current one, the loop doesn’t examine it. If you remove the current item, the loop seems to get confused and exits without raising an error.

Additions and deletions to an array are not reflected in the loop. If you use a ReDim statement to add items to the end of the array, the loop does not process them. If you try to access those objects, however, the program generates an “Index was outside the bounds of the array” error.

If you use ReDim to remove items from the end of the array, the loop processes those items anyway! If you modify the values in the array, for example, you change an object’s properties or set an array entry to an entirely new object, the loop sees the changes.

To avoid all these possible sources of confusion, don’t modify a collection or array while a For Each loop is examining its contents.

One common scenario when dealing with collections is examining every item in the collection and removing some of them. If you use a For Each loop, removing the loop’s current item makes the loop exit prematurely.

Another approach that seems like it might work (but doesn’t) is to use a For Next loop, as shown in the following code. If the code removes an object from the collection, the loop skips the next item because its index has been reduced by one and the loop has already passed that position in the collection. Worse still, the control variable i will increase until it reaches the original value of employees.Count. If the loop has removed any objects, the collection no longer holds that many items. The code tries to access an index beyond the end of the collection and throws an error.

  Dim emp As Employee For i As Integer = 1 To employees.Count     emp = CType(employees(i), Employee)     If emp.IsManager Then employees.Remove(i) Next i 

One solution to this problem is to use a For Next loop to examine the collection’s objects in reverse order, as shown in the following example. In this version, the code never needs to use an index after it has been deleted because it is counting backwards. The index of an object in the collection also doesn’t change unless that object has already been examined by the loop. The loop examines every item exactly once, no matter which objects are removed.

  For i As Integer = employees.Count To 1 Step -1     emp = CType(employees(i), Employee)     If emp.IsManager Then employees.Remove(i) Next i 

Enumerators

An enumerator is an object that lets you move through the objects contained by some sort of container class. For example, collections, arrays, and hash tables provide enumerators. This section discusses enumerators for collections, but the same ideas apply for other classes that provide enumerators.

You can use an enumerator to view the objects in a collection but not to modify the collection itself. You can use the enumerator to alter the objects in the collection, but you can generally not use it to add, remove, or rearrange the objects in the collection.

Initially, an enumerator is positioned before the first item in the collection. Your code can use the enumerator’s MoveNext method to step to the next object in the collection. MoveNext returns True if it successfully moves to a new object or False if there are no more objects in the collection.

The Reset method restores the enumerator to its original position before the first object, so you can step through the collection again.

The Current method returns the object that the enumerator is currently reading. Note that Current returns a generic Object, so you will probably need to use CType to convert the result into a more specific data type before you use it. Invoking Current throws an error if the enumerator is not currently reading any object. That happens when the enumerator is first created and it is before the first object, and after the enumerator has moved past the last object.

The following example uses an enumerator to loop through the items in a collection named m_Employees. It declares an Employee variable named emp and an IEnumerator object named employee_enumerator. It uses the collection’s GetEnumerator method to obtain an enumerator for the collection. The program then enters a While loop. If employee_enumerator.MoveNext returns True, the enumerator has successfully moved to the next object in the collection. As long as it has read an object, the program uses CType to convert the generic object returned by Current into an Employee object, and it displays the Employee object’s Title, FirstName, and LastName values. When it has finished processing all of the objects in the collection, employee_enumerator.MoveNext returns False and the While loop ends.

  Dim emp As Employee Dim employee_enumerator As IEnumerator employee_enumerator = m_Employees.GetEnumerator() Do While (employee_enumerator.MoveNext)     emp = CType(employee_enumerator.Current, Employee)     Debug.WriteLine(emp.Title & " " & emp.FirstName & " " & emp.LastName) Loop 

A For Each loop provides roughly the same access to the items in a container class as an enumerator. Under some circumstances, however, an enumerator may provide a more natural way to loop through a container class than a For Each loop. For example, an enumerator can skip several items without examining them closely. You can also use an enumerator’s Reset method to restart the enumeration. To restart a For Each loop, you would need to repeat the loop, possibly by placing it inside yet another loop that determined when to stop looping.

The Visual Basic documentation states that an enumerator is valid only as long as you do not modify the collection. If you add or remove an object to or from the collection, the enumerator throws an “invalid operation” exception the next time you use it. In at least some cases, however, this doesn’t seem to be true, and an enumerator can still work even if you modify its collection. This could lead to extremely confusing situations, however. To avoid unnecessary confusion, do not modify a collection while you are accessing it with an enumerator.

The IEnumerable interface defines the features needed for enumerators so any class that implements the IEnumerable interface provides enumerators. Any class that supports For Each must also implement the IEnumerable interface, so any class that supports For Each also supports enumerators. A few of the classes that implement IEnumerable include the following:

  • Array

  • HybridDictionary

  • SqlDataReader

  • ArrayList

  • ListDictionary

  • Stack

  • Collection

  • MessageQueue

  • String

  • CollectionBase

  • OdbcDataReader

  • StringCollection

  • ControlCollection

  • OleDbDataReader

  • StringDictionary

  • DataView

  • OracleDataReader

  • TableCellCollection

  • DictionaryBase

  • Queue

  • TableRowCollection

  • DictionaryEntries

  • ReadOnlyCollectionBase

  • XmlNode

  • Hashtable

  • SortedList

  • XmlNodeList

Iterators

An iterator is similar in concept to an enumerator. It also provides methods that allow you to step through the objects in some sort of container object. Iterators are more specialized than enumerators and work with a particular kind of class. While you can use a generic IEnumerator object to step through the items contained in any class that implements IEnumerable (an array, collection, hash table, or whatever), a certain iterator class is associated with a specific container class.

For example, a GraphicsPath object represents a series of connected lines and curves. A GraphicsPathIterator object can step through the line and curve data contained in a GraphicsPath object.

Iterators are much more specialized than enumerators. How you use them depends on what you need to do and on the kind of iterator, so they are not described in detail here.

Do Loop Statements

Visual Basic .NET supports three basic forms of Do Loop statements. The first form is a loop that repeats forever. The syntax is as follows:

  Do     statements     [Exit Do]     statements     [Continue Do]     statements Loop 

This kind of Do Loop executes the code it contains until the program somehow ends the loop. The following loop processes work orders. It calls the WorkOrderAvailable function to see if a work order is available. If an order is available, the code calls ProcessWorkOrder to process it. The code then repeats the loop to look for another work order.

  Do     ' See if a work order is available.     If WorkOrderAvailable() Then         ' Process the next work order.         ProcessWorkOrder()     End If Loop 

This example keeps checking for work orders forever. Most programs include some method for the loop to end so that the program can eventually stop. For example, the loop might use the Exit Do statement described shortly to end the loop if the user clicks a Stop button.

The second and third forms of Do Loop statements both include a test to determine whether they should continue looping. The difference between the two versions is where they place the test.

The second version of Do Loop places its test at the beginning, so the test is evaluated before the code is executed even once. If the test initially indicates that the loop should not continue, the statements inside the loop are never executed. The syntax is as follows:

  Do {While | Until} condition     statements     [Exit Do]     statements     [Continue Do]     statements Loop 

The final version of Do Loop places its test at the end. In this version, the statements inside the loop are executed before the loop performs its test. That means that the code is always executed at least once. The syntax is as follows:

  Do     statements     [Exit Do]     statements     [Continue Do]     statements Loop {While | Until} condition 

If the code uses the While keyword, the loop executes as long as the condition is true. If the code uses the Until keyword, the loop executes as long as the condition is false. Note that the statement Until condition is equivalent to While Not condition. Visual Basic provides these two variations so that you can pick the one that makes your code more readable. Use the one that makes the most sense to you.

The Exit Do statement allows the program to leave a loop before it would normally finish. For example, the following code uses an enumerator to look through the m_Employees collection. If it finds an Employee object that has title Manager, it exits the Do While Loop. Note that the loop eventually exits whether it finds a manager or not, so the code must later check to see if it found a manager.

  Dim emp As Employee Dim employee_enumerator As IEnumerator employee_enumerator = m_Employees.GetEnumerator() Do While (employee_enumerator.MoveNext)     emp = CType(employee_enumerator.Current, Employee)     If emp.Title = "Manager" Then Exit Do Loop ' Process the Manager. If emp.Title = "Manager" Then ... 

The Exit Do statement exits only the Do Loop immediately surrounding the statement. For example, the following code makes the variable R run from 1 to 10. For each value of R, the program makes variable C run from 1 to 100. Within the inner loop, the program checks cost(R, C). If that value is greater than 100, the program displays R, C, and cost(R, C) and then uses Exit Do to stop the inner loop. The loop over C ends and the code continues with the next value of R.

  R = 1 Do While R < 10     C = 1     Do While C < 100         If cost(R, C) > 100 Then             Debug.WriteLine("(" & R & ", " & C & ") = " & cost(R, C))         End If     Loop Loop  

The Continue Do statement makes the loop jump back to its Do statement and start the loop over again. This is particularly useful if the program doesn’t need to execute the rest of the steps within the loop and wants to quickly start the next iteration. Unlike a For loop, the Do loop does not automatically increment a looping variable or move to the next object in a collection. The code must explicitly change the loop’s condition before calling Continue Do or else the loop will continue forever.

While End

A While End loop is equivalent to a Do While Loop. The syntax is as follows:

  While condition     statements     [Exit While]     statements     [Continue While]     statements End While 

This is equivalent to the following:

  Do While condition     statements     [Exit Do]     statements Loop 

The End While statement exits a While End loop just as an Exit Do statement exits a Do While Loop.

The difference between While End and Do While Loop is stylistic, and you can use whichever seems clearer to you. Because Do Loop provides more flexibility, having four different versions using While or Until at the start or finish of the loop, you might want to stick to them for consistency’s sake.

Previous versions of Visual Basic ended While loops with the Wend keyword, as in the following Visual Basic 6 code:

  i = 1 While i < 5     Debug.Print i     i = i + 1 Wend 

The Wend keyword is no longer supported, so you should use End While instead.

Exit and Continue

The Exit statement lets you end a loop early. The Continue statement lets you jump to the start of a loop before reaching its end.

Both of these statements work on the innermost loop of the appropriate type. For example, the following code contains a For loop, that contains Do loop, that contains a second For loop. Within the innermost loop, an Exit For statement exits the inner For loop. An Exit Do statement exits the Do loop. There is no simple Exit statement that can exit the outer For loop from this position.

  For i As Integer = 1 To 3     Dim j As Integer = 1     Do While j < 3         For k As Integer = 1 To 3             '...             If test1 Then Exit For ' Exits the For K loop.             '...             If test2 Then Exit Do ' Exits the Do.             '...         Next k     Loop Next i 

Similarly, a Continue statement continues the innermost loop of the appropriate type: For, Do, or While.

GoTo

A GoTo statement unconditionally tells the program to jump to a specific location in the code. Because it tells the program what to do, it is a program control statement. The syntax is as follows:

      GoTo line_label     ... line_label:     ... 

While GoTo by itself isn’t a decision statement, it is often used to mimic a decision statement. For example, the following code fragment uses GoTo to mimic an If Then Else statement. It examines the purchase_ total variable. If purchase_total is less than 1000, the code jumps to the line labeled SmallOrder. If purchase_total is greater than or equal to 1000, the program continues to execute the code that processes a larger order.

      If purchase_total < 1000 Then GoTo SmallOrder     ' Process a large order.     ...     Exit Sub SmallOrder:     ' Process a small order.     ... 

The following code does roughly the same thing as the previous version but without the GoTo statement:

  If purchase_total < 1000 Then     ' Process a large order.     ... Else     ' Process a small order.     ... End If 

Similarly, GoTo is sometimes used to build a loop. The following code uses GoTo to jump backward in the code to call subroutine DoSomething 10 times:

      Dim i As Integer = 1 StartLoop:     DoSomething()     i += 1     If i <= 10 Then GoTo StartLoop 

The following code does the same thing without the GoTo statement:

  For i As Integer = 1 To 10     DoSomething() Next i 

The problem with the GoTo statement is its flexibility. By using GoTo in a haphazard way, an undisciplined programmer can make the program jump all over the place with little rhyme or reason. This can lead to spaghetti code (so called because a diagram showing the program’s flow of control can look like a pile of spaghetti) that is extremely difficult to understand, debug, and maintain.

Many programming groups prohibit any use of GoTo because it can lead to this kind of code. Some even believe GoTo should be removed from the Visual Basic language. You can always use If Then Else statements, For Next loops, While loops, and other control statements in place of GoTo statements, so GoTo is not absolutely necessary.

However, some programmers feel that GoTo simplifies code under certain very specific circumstances. The following code begins by performing some sort of initialization. It may open databases, create temporary files, connect to the Internet, and perform other startup chores. It then executes a series of tasks, each of which may fail or otherwise make it pointless for the program to continue. If any of these steps sets the variable should_stop to True, the program uses a GoTo statement to jump to its clean up code. This code closes any open database, deletes temporary files, closes permanent files, and performs any other necessary clean up chores.

  ' Get started, open database, open files, etc. Initialize() ' Perform a long series of tasks. DoStuff1() If should_stop Then GoTo CleanUp DoStuff2() If should_stop Then GoTo CleanUp DoStuff3() If should_stop Then GoTo CleanUp ... CleanUp:     ' Close database, delete tempporary files, etc.     PerformCleanUp() 

The GoTo statement in this code lets the program jump to the clean-up code any time it needs to stop performing its tasks. That may be because a task failed, the user canceled the operation, or all the tasks are finished.

Note that this is a very specific use of GoTo. The code only jumps forward, never backward. It also only jumps to clean-up code, not to some arbitrary point in the code. These facts help make the GoTo statement easier to understand and prevent spaghetti code.

The following code does the same thing as the previous version without using GoTo. At each step, the program checks the value of should_stop to see if it should continue working through its tasks.

  ' Get started, open database, open files, etc. Initialize() ' Perform a long series of tasks. DoStuff1() If Not should_stop Then DoStuff2() If Not should_stop Then DoStuff3() ' Close database, delete tempporary files, etc. PerformCleanUp() 

The following code shows another version that doesn’t use GoTo. This version places the code that formerly contained the GoTo statement in a new subroutine. Instead of using GoTo, this routine uses Exit

  Sub to stop performing tasks early if necessary.     Sub DoWork()     ' Get started, open database, open files, etc.     Initialize()     ' Perform all of the tasks.     PerformTasks()     ' Close database, delete tempporary files, etc.     PerformCleanUp() End Sub ' Perform a long series of tasks. Sub PerformTasks()     DoStuff1()     If should_stop Then Exit Sub     DoStuff2()     If should_stop Then Exit Sub     DoStuff3()     If should_stop Then Exit Sub End Sub 

Conceptually, an Exit Sub statement is little different from a GoTo statement. After all, it, too, is an unconditional jump command. However, Exit Sub has a very specific, well-known effect: It makes the program stop executing the current subroutine. It cannot make the program jump around arbitrarily, possibly leading to spaghetti code.

If you ever feel tempted to use GoTo, take a few moments to think about ways you might rewrite the code. If the only ways you can think of to rewrite the code are more confusing than the original version, go ahead and use GoTo. You should probably add some fairly detailed comments to ensure that the GoTo statement doesn’t cause trouble later.




Visual Basic 2005 with  .NET 3.0 Programmer's Reference
Visual Basic 2005 with .NET 3.0 Programmer's Reference
ISBN: 470137053
EAN: N/A
Year: 2007
Pages: 417

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