Variable Scope



Scope was first introduced when we formally defined the attributes that make up a variable (recall). In simplest terms, scope defines where in a program a variable can be accessed; that is used, assigned, output, etc. A bit more formally, a programming element (e.g. a variable) is available for use throughout the "region" in which it is declared. All code in the same region can refer to the element without qualifying its name. Scope regions (in VB) are divided into three categories: local, module level and namespace level scope (with local scope being subdivided further). These levels of scope progress from the narrowest scope (block) to the widest scope (namespace); where the narrowest scope implies the smallest set of code that can reference or use the element.

Local Scope

Block Scope

A block is a set of statements typically terminated by an End, Else, Loop, or Next statement. Examples include within a For...Next loop or an If...Then...Else...End If construct. An element declared within a block can be used only within that block. In the following example, the scope of the Integer variable intFoo is local to the block of the For...Next loop since it is declared within the loop.
	For intFoo As Integer = 1 To 5

	    Debug.Print("intFoo = " & intFoo.ToString)

	Next
	
	'Debug.Print(intFoo.ToString)
If we un-comment the Debug.Print statement following the Next statement above, we would get a compile error stating "Name 'intFoo' is not declared." This should be obvious at this point since the scope of the variable is only within the local block.

Note: even if the scope of an element is limited to a block, its lifetime is still that of the entire procedure. If you enter the block more than once during the procedure, a block variable retains its previous value. To avoid unexpected results in such a case, it is wise to initialize the variable each time. In the example above, the variable is automatically initialized in the execution of the For statement.

Procedure Scope

An element declared within a procedure is available everwhere inside that procedure. Only the procedure that contains the declaration can use it. Variables at this level are often known as local variables, i.e. local to that specific procedure. Local variables are declared using the Dim statement (with or without the Static keyword). My preference is that all local variables are defined at the top of the procedure, one to a line.

Procedure and block scope are closely related; if an element is declared inside a procedure but outside any block within that procedure, the element can be thought of as having block scope, where the block is the entire procedure. Note all local elements, even if they are Static variables, are private to the procedure in which they appear. You cannot declare an element using the access keyword Public within a procedure.

Module Scope

Variables for which you give module level access are available for use by every procedure in that module, but not to any code in a different module. Module level variables are declared by placing the declaration statement outside of any procedure or block within the module, class, or structure, preferably at the top of the module, class or structure. The access keyword Private is typically used to declare a variable of this scope. The Dim statement at module level defaults to Private if you do not use any accessibility keywords. However, you can make the scope and accessibility more obvious by using the Private keyword in the Dim statement.

In the following example, the Integer variable intFoo is available to all procedures defined in the module. When the second procedure is called, it displays the value of the Integer variable.

	' Put the following declaration at module level (not in any procedure) 
	Private intFoo As Integer
		
	Sub InitializeModuleVariable() 

   	    intFoo = 42

	End Sub 

	Sub DisplayModuleVariable() 

   	    Debug.Print("intFoo = " & intFoo.ToString)

	End Sub 
Note that any procedure in the module where the variable was declared can change the value of a module level variable, whether intending to or not!

Namespace Scope

If you declare an element at module level using the Friend or Public keyword, it becomes available to all procedures throughout the namespace in which the element is declared. With the following alteration to the preceding example, the string variable strMsg can be used by code anywhere in the namespace of its declaration:
' Include this declaration at module level (not inside any procedure). 
Public strMsg As String   ' strMsg is available throughout the namespace. 
Namespace scope includes nested namespaces. An element available from within a namespace is also available from within any namespace nested inside that namespace. If your project does not contain any Namespace statements, everything in the project is in the same namespace. In this case, namespace scope can be thought of as project scope. Public elements in a module, class, or structure are also available to any project that references their project.

Which Scope To Use?

The million dollar question (well, maybe hundred dollar) after reading the above is "which scope should I use?"


Next Section: Testing and Debugging Table of Contents


©2009, Mark A. Thomas. All Rights Reserved.