Scope refers to the visibility and life of a data item or object. Perhaps an example will help you to understand the concept of scope. Chapter 6, "String Variables ," discusses a number of string functions that Visual Basic .NET provides. Some examples of these are the Len() , Left() , Right() , and Mid() functions.
In a sense, these string functions are like black boxes. You shove some data through the front door of the black box, and some desired result emerges from the back door. You can't see what's inside the black box. You have no idea what variables, objects, or other data items might be used inside the box. Although you can be relatively sure that some data items are being used inside the black box, it's an exclusive club to which you don't belong. In other words, the data that is defined inside the black box is not visible to you. Because you know nothing about the black box's data, the scope of the data being used inside the black box is visible (and usable) only inside the black box.
The concept of scope, therefore, relates to the accessibility of a data item or object. In most cases, you want to limit the scope of an object. That is, you want to keep the scope of a data item confined to only those objects and methods that need to have access to it. The more data that you can hide in little black boxes, the less chance there is of someone or something else messing it up. You want to define your data in such a way that the data exists only on a "need-to-know" basis. In OOP terms, you want to encapsulate your data as much as possible.
In the following sections you'll write a short program that will expand your understanding of what scope is and how you can use it to your advantage.
Local (Procedural) Scope
To examine the concept of scope in greater detail, you should create a new project and name it LocalScope . Add two buttons to the form and name them btnCalc and btnExit . The form should look something like the form shown in Figure 8.1.
Figure 8.1. The form for the LocalScope project.
Add the code shown in Listing 8.1 to the btnCalc object's Click() event.
Listing 8.1 Code for the btnCalc Object's Click() Event
Private Sub btnCalc_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnCalc.Click Dim MyVariable As Integer MyVariable = 10 End Sub
All you've done is define a variable named MyVariable and assigned the value 10 to it. Now you need to copy the assignment statement to the btnExit object's Click() event so that its code reads as follows :
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnExit.Click MyVariable = 10 Me.Dispose() End Sub
If you compile the program, what happens? You get the following error message:
'MyVariable' is not declared.
That's strange . You defined the variable named MyVariable in the btnCalc object's Click() event, but Visual Basic .NET is telling you it has no clue what MyVariable is.
The reason Visual Basic .NET doesn't know about MyVariable in the btnExit object's Click() event is that you defined MyVariable in the btnCalc object's Click() event. Whenever you define a variable within a subroutine, as you did with MyVariable , the scope of that variable extends from its definition statement (that is, its Dim statement) to the end of the subroutine in which it is defined. Therefore, MyVariable 's scope extends only from the Dim statement to the End Sub for the btnCalc object's Click() event. This is an example of local scope. A variable with local scope exists only within the subroutine or function in which it is defined.
Because you tried to use MyVariable inside btnExit , Visual Basic .NET does not know about MyVariable because it is out of scope. The scope for MyVariable does not extend to the btnExit subroutine; therefore, there is no way for Visual Basic .NET to know about MyVariable outside btnCalc . Listing 8.2 shows the scope for MyVariable .
Listing 8.2 The Local Scope for MyVariable
Private Sub btnCalc_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnCalc.Click Dim MyVariable As Integer ' MyVariable scope starts here.... ' ...still in scope... MyVariable = 10 ' ...still in scope... ' ...still in scope... End Sub ' MyVariable scope ends here...out of scope
The important thing to keep in mind about local scope is that variables that have local scope only live within the function or subroutine in which they are defined.
How does Visual Basic .NET keep track of a variable's scope? You don't really need to know the details of how Visual Basic .NET tracks a variable's scope; basically, it uses a coding scheme to index each variable's scope and maintains that information in the symbol table.
Scope and Duplicate Definition Errors
Another way to prove the idea of local scope is to place a second definition for MyVariable at the same local scope level as the first. This is shown in Listing 8.3.
Listing 8.3 Two Variables with the Same Name and the Same Scope
Private Sub btnCalc_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnCalc.Click Dim MyVariable As Integer MyVariable = 10 Dim MyVariable As Integer End Sub
You should make the code changes shown in Listing 8.3. (It's the same as Listing 8.1, except for the second Dim statement.) Then if you compile the program, you get this error message:
Local variable 'MyVariable' is already declared in the current block.
Visual Basic .NET is trying to tell you, "I'm confused . You have already defined a variable named MyVariable at this scope level, and now you're trying to do it again. Don't do that!" In other words, Visual Basic .NET has looked in the symbol table and found that a variable called MyVariable already exists at that scope level. Because two variables cannot have the same name at the same scope level, Visual Basic .NET has no choice but to issue an error message.
The Same Variable Name, Different Scope Levels
What would happen if you used the same variable name as before but defined it in a different procedure? To see what happens in this case, place a duplicate definition statement for MyVariable in the btnExit object's Click() event. The code for both events appears in Listing 8.4.
Listing 8.4 Variable Definitions with the Same Name but Different Levels of Local Scope
Private Sub btnCalc_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnCalc.Click Dim MyVariable As Integer MyVariable = 10 End Sub Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnExit.Click Dim MyVariable As Integer MyVariable = 20 Me.Dispose() End Sub
Now if you try to compile the program, you don't have any problem, do you? Why doesn't Visual Basic .NET complain about the variable named MyVariable being defined twice in the program? The reason Visual Basic .NET doesn't complain is because they are not the same variable. The variable named MyVariable that is defined in the btnCalc object's Click() event has a level of scope that extends only to the End Sub statement for the btnCalc object's Click() event; that is, MyVariable only lives inside the btnCalc object's Click() event. MyVariable is invisible outside the btnCalc object's Click() event. The two MyVariable variables are different variables with different lvalue values. The same applies to the MyVariable variable defined in the btnExit object's Click() event. It lives only within the body of the btnExit object's Click() event subroutine. Outside that subroutine, MyVariable does not exist.
Because each instance of MyVariable has a scope that is limited to the subroutine in which it is defined, there is no name conflict between subroutines. Local scope means the life and visibility of a variable with local scope are limited to the procedure body in which it is defined.
Clearly, local scope is a good thing for variables because it has a black-box effect. In essence, the black box is the statement body for the procedure in which the variable is defined. There is no way for anything outside the statement body to access a variable with local scope. This also means there is no way for any outside agent to alter the value of a data item that has local scope. In almost all situations, this data privacy is a good thing.