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 is True, or run while some condition is False.

Broadly speaking, there are two types of looping statements. For Next loops execute a certain number of times that (in theory at least) is known. For example, a For Next loop may execute a series of statements 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 know 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 a program uses the InputBox function to get names from the user until the user clicks the Cancel button. In that case, there’s no way for the program to guess how many values the user will enter before canceling.

The following sections describe the looping statements supported by Visual Basic .NET. The next two sections describe For Next loops, and the sections after those describe While loops. (Example program Loops, which is available for download on the book’s website, demonstrates some of these kinds of 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. Note that the loop may not execute even once depending on 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 = As Integer 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

Visual Basic doesn’t require that you include the variable’s name in the Next statement, although this makes the code easier to read. If you do 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 Option Explicit is on and Option Infer is off, then 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

Declaring the looping variable in the For statement is a good practice for several reasons. 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 instead of a For Next loop.

The Exit For statement allows the program to leave a For Next 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 Next loop immediately surrounding the statement. If a For Next loop is nested within another For Next loop, the Exit For statement exits only the inner loop.

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’s body and wants to start the next iteration quickly.


OUT OF CONTROL
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, these data types are subject to rounding errors that can lead to unexpected results in For Next loops. The preceding 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 if you have Option Explicit on and Option Infer off.


ENABLING ENUMERATORS
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.

That means if a collection or array contains more than one type of object, the control variable must be of a type that can hold all of the objects. If the objects in a collection do not inherit from a common ancestor class, the code must use a control variable of type Object.

Like For Next loops, For Each loops support the Exit For and Continue For statements.

As is the case with For Next loops, declaring the looping 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, don’t bother.

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’s behavior. 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.


CREATIVE COLLECTIONS
If you really must modify a collection while looping through it, create a new collection and modify that one instead. For example, suppose you want to loop through the original collection and remove some items. Make the new collection and then loop through the original, copying the items that you want to keep into the new collection.
In really complicated situations, you may need to use a While loop and some careful indexing instead of a For Each loop.

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 = employees(i)
    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 backward. 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 = employees(i)
    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 these other classes.

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 (for example, to change their properties), 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 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 if the enumerator is before the first object or after the last object.

The following example uses an enumerator to loop through the items in a collection named Employees:

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

This code 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.


EXACT ENUMERATORS
Some containers support enumerators that use more specific data types. For example, a program can use a generic List that contains a specific kind of object such as Employee. Then it can use a generic enumerator of the correct type, in this case IEnumerator(Of Employee). In that case, the enumerator’s Current property returns an Employee instead of an Object so the code does not need to convert it into an Employee before using its methods.
Example program EnumerateEmployees, which is available for download on the book’s website, creates a generic List(Of Employee). It then creates a generic IEnumerator(Of Employee) for the list and uses it to loop through the list. For more information on generics, see Chapter 26, “Generics.”

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 determines 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. Although you can use a nonspecific 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 next version of Do Loop places its test at the beginning, so the test is evaluated before the code is executed. 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 the nearest enclosing Do loop before it would normally finish. 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.


NOTE
Example program ExitAndContinue, which is available for download on the book’s website, demonstrates the Exit and Continue statements for Do and For loops.

Unlike a For Next or For Each 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 reaching the Loop statement or 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 Loop:

Do While condition
    statements
    [Exit Do]
    statements
    [Continue Do]
    statements
Loop

The Exit While statement exits a While End Loop just as an Exit Do statement exits a Do While Loop. Similarly, Continue While makes the program return to the top of the loop just as Continue Do does for Do loops.

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.3.204