SCOPE

A variable’s scope determines which other pieces of code can access it. For example, if you declare a variable inside a subroutine, only code within that subroutine can access the variable. The four possible levels of scope are (in increasing size of scope) block, procedure, module, and namespace.

Block Scope

A block is a series of statements enclosed in a construct that ends with some sort of End, Else, Loop, or Next statement. If you declare a variable within a block of code, the variable has block scope, and only other code within that block can access the variable. Furthermore, only code that appears after the variable’s declaration can see the variable.

Variables declared in the block’s opening statement are also part of the block. Note that a variable is visible within any sub-block contained within the variable’s scope.

For example, consider the following code snippet:

For i As Integer = 1 To 5
    Dim j As Integer = 3
    If i = j Then
         Dim M As Integer = i + j
         Debug.WriteLine("M: " & M)
    Else
         Dim N As Integer = i * j
         Debug.WriteLine("N: " & N)
    End If
             
    Dim k As Integer = 123
    Debug.WriteLine("k: " & k)
Next i

This code uses a For loop with the looping variable i declared in the For statement. The scope of variable i is block-defined by the For loop. Code inside the loop can see variable i, but code outside of the loop cannot.

Inside the loop, the code declares variable j. This variable’s scope is also the For loop’s block.

If i equals j, the program declares variable M and uses it. This variable’s scope includes only the two lines between the If and Else statements.

If i doesn’t equal j, the code declares variable N. This variable’s scope includes only the two lines between the Else and End If statements.

The program then declares variable k. This variable also has block scope, but it is available only after it is declared, so the code could not have accessed it earlier in the For loop.

Other code constructs that define blocks include the following:

  • Select Case statements — Each Case has its own block.
  • Try Catch statements — The Try section and each Exception statement defines a block. Note also that the exception variable defined in each Exception statement is in its own block. (That means they can all have the same name.)
  • Single-line If Then statements — These are strange and confusing enough that you should avoid them, but the following code is legal:
        If is_manager Then Dim txt As String = "M" : MessageBox.Show(txt) Else _
        Dim txt As String = "E" : MessageBox.Show(txt)
  • While loops — Variables declared inside the loop are local to the loop.
  • Using statements — Resources acquired by the block and variables declared inside the block are local to the block.

Because block scope is the most restrictive, you should use it whenever possible to reduce the chances for confusion. The section “Restricting Scope” later in this chapter talks more about restricting variable scope.

Procedure Scope

If you declare a variable inside a subroutine, function, or other procedure, but not within a block, the variable is visible to any code inside the procedure that follows the declaration. The variable is not visible outside of the procedure. In a sense, the variable has block scope where the block is the procedure.

A procedure’s parameters also have procedure scope. For example, in the following code, the scope of the order_object and order_item parameters is the AddOrderItem subroutine:

Public Sub AddOrderItem(order_object As Order, order_item As OrderItem)
    order_object.OrderItems.Add(order_item)
End Sub

Module Scope

A variable with module scope is available to all code in its code module, class, or structure, even if the code appears before the variable’s declaration. For example, the following code works even though the DisplayLoanAmount subroutine is declared before the LoanAmount variable that it displays:

Private Class Lender
    Public Sub DisplayLoanAmount()
        MessageBox.Show(LoanAmount)
    End Sub
             
    Private LoanAmount As Decimal
    ...
End Class

To give a variable module scope, you should declare it with the Private, Protected, or Protected Friend keyword. If you declare the variable Private, it is visible only to code within the same module.

If you declare the variable Protected, it is accessible only to code in its class or a derived class. (Remember that you can only use the Protected keyword in a class.)

A Protected Friend variable is both Protected and Friend, so it is available only to code that is inside the variable’s class or a derived class (Protected) and within the same project (Friend).

These keywords apply to both variable and procedure declarations. For example, you can declare a subroutine, function, or property procedure Private, Protected, or Protected Friend.

For more information on accessibility keywords, see the section “Accessibility” earlier in this chapter.

Example program ScopeTest, which is available for download on the book’s website, demonstrates module and procedure scope.

Namespace Scope

By default, a project defines a namespace that includes all the project’s variables and code. However, you can use Namespace statements to create other namespaces if you like. This may be useful to help categorize the code in your application.

If you declare a variable with the Public keyword, it has namespace scope and is available to all code in its namespace, whether inside the project or in another project. It is also available to code in any namespaces nested inside the variable’s namespace. If you do not create any namespaces of your own, the whole project lies in a single namespace, so you can think of Public variables as having global scope.

If you declare a variable with the Friend keyword, it has namespace scope and is available to all code in its namespace within the same project. It is also available to code in any namespaces nested inside the variable’s namespace within the project. If you do not create any namespaces of your own, the whole project lies in a single namespace so you can think of Friend variables as having project scope.

For more information on the Public and Friend keywords, see the section “Accessibility” earlier in this chapter.

Restricting Scope

There are several reasons why you should give variables the most restrictive scope possible that still lets them do their jobs.

Limited scope keeps the variable localized so that programmers cannot use the variable incorrectly in far off code that is unrelated to the variable’s main purpose.

Having fewer variables with global scope means programmers have less to remember when they are working on the code. They can concentrate on their current work, rather than worrying about whether variables r and c are declared globally and whether the current code will interfere with them.

Limiting scope keeps variables closer to their declarations, so it’s easier for programmers to check the declaration. One of the best examples of this situation is when a For loop declares its looping variable right in the For statement. A programmer can easily see that the looping variable is an integer without scrolling to the top of the subroutine hunting for its declaration. It is also easy to see that the variable has block scope, so other variables with the same names can be used outside of the loop.

Limited scope means a programmer doesn’t need to worry about whether a variable’s old value will interfere with the current code, or whether the final value after the current code exits will later interfere with some other code. This is particularly true for looping variables. If a program declares variable i at the top of a subroutine, and then uses it many times in various loops, you might need to do a little thinking to be sure the variable’s past values won’t interfere with new loops. If you declare i separately in each For statement, each loop has its own version of i, so there’s no way they can interfere with each other.

Finally, variables with larger scope tend to be allocated more often, so they take up memory more often. For example, block variables and non-static variables declared with procedure scope are allocated when they are needed and are destroyed when their scope ends, freeing their memory. A variable declared Static or with module or namespace scope is not freed until your application exits. If those variables are large arrays, they may take up a lot of memory the entire time your application is running.

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

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