3.1 VariablesA variable can be defined as an entity that has the following six properties:
3.1.1 Variable ScopeVariables (and constants) have a scope , which indicates where in the program the variable is recognized or visible to the code ” that is, where it can be referred to in code. 3.1.1.1 Local variables: block-level and procedure-level scopeIf a variable is declared inside a code block (a set of statements that is terminated by an End... , Loop , or Next statement), then the variable has block-level scope ; that is, it is visible only within that block. For example, consider the following code: If x <> 0 Then Dim rec As Integer rec = 1/x End If MsgBox CStr( rec ) In this code, the variable rec is not recognized outside the block in which it is defined, so the final statement produces an error. It is important to note that the lifetime of a variable always refers to the entire procedure, even if the variable's scope is block-level. (We discuss this in Section 3.1.2 later in this chapter.) This implies that if a block is entered more than once, a block-level variable will retain its value from the previous time the block code was executed. A variable declared using the Dim keyword within a Visual Basic procedure but not within a code block has procedure-level scope . Its scope consists of the procedure in which it is declared. A variable that has block-level scope or procedure-level scope is called a local variable. One of the advantages of local variables is that the same name can be used in different procedures without conflict, since each variable is visible only to its own procedure. Another is that the memory allocated to the variable can be released as soon as control leaves the procedure, making our code easier to maintain. 3.1.1.2 Module-level and project-level scopeThere are differences in the way scope is handled for variables declared in the Declarations section of a standard module and a class module. We restrict our discussion here to standard modules, postponing a discussion of class modules until Chapter 4. We first note that a standard module itself can be declared using one of the access modifiers Public , Friend , or Private (this is the default). Using such a modifier simply restricts the individual members to that level of access at most. Thus, for instance, a Public variable declared in a Friend module has only Friend scope. 3.1.1.2.1 Private accessA variable declared in the Declarations section of a standard module using the Private access modifier has module-level scope ; that is, it is visible in the entire module, but nowhere else. Using the Dim keyword also gives the variable module-level scope, but its use is not as clear and should be avoided for readability sake. 3.1.1.2.2 Friend accessA variable declared in the Declarations section of a standard module using the Friend access modifier is visible in the entire project and thus has project-level scope . However, it is not visible to other projects. 3.1.1.2.3 Public accessA variable declared in the Declarations section of a Public standard module using the Public access modifier is visible not only to the project in which it is declared, but also to any external project that holds a reference to the project. For instance, consider the following module declared in Project1: Public Module Module1 Public iModulePublic As Integer Friend iModuleFriend As Integer End Module If Project2 has a reference to Project1, then we can write: Project1.Module1.iModulePublic = 100 However, the code: Project1.Module1.iModuleFriend = 100 generates a "not accessible" syntax error. 3.1.2 Variable LifetimeVariables also have a lifetime . The difference between lifetime and scope is quite simple. Lifetime refers to when , or at what time during program execution the variable is valid; scope refers to where in the program the variable is recognized by (visible to) the code. To illustrate the difference, consider the following procedure: Sub ProcedureA( ) Dim LocalVar As Integer = 0 Call ProcedureB LocalVar = 1 End Sub Note that LocalVar is a local variable. When the line: Call ProcedureB is executed, execution switches to ProcedureB . While the lines of ProcedureB are being executed, the variable LocalVar is out of scope since it is local to ProcedureA . But it is still valid. In other words, the variable still exists and has a value. It is simply not accessible to the code in ProcedureB . In fact, ProcedureB could also have a local variable named LocalVar , which would have nothing to do with the variable of the same name in ProcedureA . Once ProcedureB has completed, execution continues in ProcedureA with the line: LocalVar = 1 which is a valid instruction, since the variable LocalVar is back in scope. Thus, the lifetime of the local variable LocalVar extends from the moment ProcedureA is entered to the moment it is terminated, including the period during which ProcedureB is being executed as a result of the call to this procedure, even though during that period, LocalVar is out of scope. We mention again that the lifetime of a block-level variable is the lifetime of the procedure in which it is defined. 3.1.2.1 Static variablesWe have seen that a variable may go in and out of scope during its lifetime. However, once the lifetime of a variable expires , the variable is destroyed and its value is lost. It is the lifetime that determines the existence of a variable; its scope determines its visibility. Thus, consider the following procedures: Sub ProcedureA( ) Call ProcedureB Call ProcedureB Call ProcedureB Call ProcedureB Call ProcedureB End Sub Sub ProcedureB( ) Dim x As Integer x = 5 . . . End Sub When ProcedureA is executed, it simply calls ProcedureB five times. Each time ProcedureB is called, the local variable x is created anew and destroyed at the end of that call. Thus, x is created and destroyed five times. Normally, this is just what we want. However, there are times when we would like the lifetime of a local variable to persist longer than the lifetime of the procedure in which it is declared. For example, we may want a procedure to do something special the first time it is called, but not in subsequent times. A static variable is a local variable whose lifetime is the lifetime of the entire program. The following VB code shows how one might use a static variable: Sub test( ) Static bFirstTime As Boolean = True If bFirstTime Then Debug.WriteLine("first time") bFirstTime = False Else Debug.WriteLine("not first time") End If End Sub Note that we can initialize a static variable, provided that we do so within the variable declaration . The following code illustrates this point: Sub StaticTest( ) Static st As Boolean = True ' initialize static variable MsgBox(st) st = False End Sub Private Sub button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles button1.Click StaticTest( ) End Sub The first time we hit the button1 command button, StaticTest displays the message True , because the static variable st has been initialized to True . However, all subsequent times we hit the button, StaticTest returns False . This ability to initialize a static variable was missing and was a very annoying oversight in earlier versions of VB. We could accomplish the same effect by using a module-level variable to keep a record of whether the procedure has been called, instead of a static local variable. However, it is considered better programming style to use the most restrictive scope possible, which, in this case, is a local variable with an "extended" lifetime. This helps prevent accidental alteration of the variable in other portions of the code. (Remember that this code may be part of a much larger code module, with a lot of things going on.) |