Variables – Part 2

Declaration and Scope

 

What is Scope?

The scope (or visibility) of an element in code is all the code that can refer to it without qualifying its name. Stated other way, an element's scope is it's accessibility in code. Scope is normally used when writing large programs as large programs divide code into different classes, modules, etc. Also, scope prevents the chance of code referring to the wrong item.

The syntax for declaring a variable in VB is as follows:

 

[Dim | Private | Public | Static | Protected | Friend | Protected Friend] variablename [As datatype]

 

Note that you use one of seven keywords to declare a variable; which one you use depends on the scope you want the variable to have.  Levels of scope are:

·         project-level (also called "global" or "application" scope;  the variable is accessible to all procedures in all modules of the project)

·         module-level (the variable is accessible to all procedures in the module in which it is declared)

·         local-level (the variable is accessible only to the procedure in which it is declared)

·         block level (the element declared is available only within the code block in which it is declared)

In addition to the keyword used to declare the variable, the location of the variable declaration also affects its scope.  A variable may be declared in one of two places:

 

·         The General Declarations Section of a form or standard module.  This section of a module is not labeled as such; it simply exists at the beginning of a code module, after the "Option Explicit" statement but prior to the first Sub or Function procedure.  Declaring a variable here makes it a project-level variable (if the Public keyword is used) or a module-level variable (if the Private or Dim keyword is used).

 

·         Within a Sub or Function procedure.  Declaring a variable here makes it a local-level variable; only the Dim or Static keyword can be used here.  The recommended practice is to declare all local variables within a procedure immediately following the Sub or Function header and prior to any executable statements (although VB will allow you to declare variables anywhere within the procedure).

 

What is Accessibility?

 

Accessibility means the permission for code to read or write to an element. In other words, it’s the restriction to access the element (variable or subroutines) which is decided by you using the keywords mentioned above, these keywords are also known as Access Modifiers.  The table below shows the access modifiers in detail:

 

Access Modifier

Affect on Elements

Public 

Can be accessed from anywhere.

Private 

Can be accessed only by members within the type that defines it.

Friend 

Can be accessed from all types within the assembly, but not from outside the assembly.

Protected 

Can be accessed only by members within the type that defines it or types that inherit from that type.

Protected Friend

Can be accessed from all types within the assembly or from types inheriting from the owning type. This is the union of Protected (protected) and Friend (internal) access.

 

The following table shows how the seven different declarative keywords and the location of their declaration affects the scope:

 

Keyword Used to Declare the

Variable:

$

Where Declared

à

 

General Declarations Section of a Form (.frm) Module

 

General Declarations Section of a Standard (.bas) Module

 

Sub or Function procedure of a Form or Standard Module

Dim (preferred keyword for local-, but not module-level variables)

module-level scope

module-level scope

local-level scope (value of the variable is NOT preserved between calls

Static

not allowed

not allowed

local-level scope (value of the variable is preserved between calls)

Private (preferred keyword for module-level variables)

module-level scope

module-level scope

not allowed

 

 

Public

project-level scope (but references to the variable must be qualified with the form name; also there are some minor restrictions on the types of variables that can be declared as public in a form)

 

project-level scope

 

not allowed

Protected

Module- level scope

Module-level scope

not allowed

Friend (This is only allowed in classes not in standard modules)

 

Assembly level scope

 

not allowed

 

not allowed

Protected Friend (This is only allowed in classes not in standard modules)

 

Assembly level scope

 

not allowed

 

not allowed

 

 

If the "As datatype" clause is omitted in a variable declaration, the variable type defaults to Object, unless a type declaration character is used. (Note: In previous versions of VB, the default data type was Variant, which does not exist in VB.NET.)

 

The following two statements both declare an integer called "intCounter" (the "As" version is preferred):

 

            Dim intCounter As Integer

            Dim intCounter%

 

The following two statements both declare an Object variable called "objWhatever":

 

            Dim objWhatever As Object

            Dim objWhatever

 

In VB .NET the String variables can be only of variable-length, and not fixed-length (as was allowed in VB6 and earlier).  The difference in declaring them is shown below:

 

'Variable-length string, length changes depending upon length of whatever is assigned to it:

Dim strPlayerName As String

 

'Fixed-length string, always 2 bytes (legal in VB6 and earlier, illegal in VB.NET)

Dim strStateAbbrev As String * 2          ' ILLEGAL IN VB.NET  

 

 

Note: Protected, Friend, or Protected Friend will not be used in the sample applications presented here.

 

Static Variables

 

The Static keyword is rarely used. It allows a local variable to retain its value after it goes out of scope.

 

Suppose you have a Sub in a form called CountThem that looks like this:

 

Private Sub CountThem()

 

    Dim    intI As Integer

    Static intJ As Integer

    intI = intI + 1

    intJ = intJ + 1

    Debug.Print("intI = " & intI & ",  intJ = " & intJ)

 

End Sub

 

Suppose you have some other Sub that calls CountThem three times in a row:

 

      Call CountThem

      Call CountThem

      Call CountThem

 

The following output from Debug.Print would be as follows:

intI = 1, intJ = 1

intI = 1, intJ = 2

intI = 1, intJ = 3

 

Note that the "regular" variable, intI, declared with "Dim", does not retain its value between calls, whereas the Static variable, intJ, does. Rather than use “Static”, it would be preferred to declare “intJ” at the module- or form-level (i.e. outside of all the Sub and Function procedures, with the keyword “Private” or “Dim”).

 

Note: In VB6, the keyword "Static" can also be used in the Sub procedure header, which causes all variables in that procedure to be static. This option is no longer available in VB.NET (i.e., the static modifier is not a valid modifier for procedure).

 

 

 

Multiple Declarations on One Line

 

VB .NET allows you to declare any number of variables on one line – you don’t need to explicitly provide the data type of each variable,   For example:

 

            Dim intA, intB, intC As Integer

 

The above statement declares intA and intB and intC as Integer type values.

I recommend declaring only one variable per line.

 

 

 

Initialization of Variables

Variables can be declared and initialized in Visual Basic .NET on a single line. Thus you may write:

Dim strVar As String = "This is a string."
 

The above statement declares a String variable and initializes its value to “This is a string”. Similarly, you can declare and initialize more than one variable on a single line:

Dim intX As Integer = 6, intY As Integer = 9

 

However, each variable does have a default initialization value.  Numeric variable types are initialized to zero, Strings are initialized to "", Booleans are initialized to False, etc.

 

 

 

The Strict and Explicit options

 

Previous versions of VB (classic VB), as well as BASIC before that, did not require that variables be declared before they were used. VB.NET also carries on this “tradition” in permitting this practice, however the default behavior of VB.NET is to throw an exception if you attempt to use a variable that hasn’t been declared previously. If an undeclared variable’s name appears in your code, the editor will underline the variable’s name with a wiggly red line indicating that it caught an error. Rest the mouse pointer on that line to see the description of the error. This means that Option Explicit is on – that is the default setting, and you should keep it that way.

 

Another related option is Option Strict, which is OFF by default. Option Strict tells the compiler whether the variables should be strictly typed or not. A strictly typed variable can only accept values of the same type it was declared with. Some purists will advocate that this option be turned on, however I am of the opinion that this option is too restrictive and I am fine with leaving the default setting (off) as is.

 

 

LEGAL VS. ILLEGAL VARIABLE DECLARATIONS

 

The figure below attempts to highlight concepts of variable declaration and scoping discussed previously:

 

PROJECT

(Form1)

Public Class Form1

 

'General Declarations Section …

 

Public  intA As Integer

Private intB As Integer

 

Private Sub MySub1()

 

    Dim intC As Integer

 

    intC = intA  'OK – intA is public (declared in this form)

    intC = intW  'OK – intW is public (declared in Module1)

    intC = intB  'OK – intB is a module-level variable of this form

    intC = intD  'Error – intD is local to MySub2

    intC = intX  'Error – intX is private to Module1

 

End Sub

 

 

Private Sub MySub2()

 

   Dim intD As Integer

 

   intD = intA  'OK – intA is public (declared in this form)

   intD = intW  'OK – intW is public (declared in Module1)

   intD = intB  'OK – intB is a module-level variable of this form

   intD = intC  'Error – intC is local to MySub1

   intD = intX  'Error – intX is private to Module1

 

End Sub

 

End Class

 

 (Module1)

Module Module1

 

'General Declarations Section ...

Public  intW As Integer

Private intX As Integer

 

Public Sub MySub3()

 

    Dim intY As Integer

 

    intY = intA         'Error – qualification required

    intY = Form1.intA   'OK – intA is public (declared in Form1)

    intY = intW         'OK – intW is public (declared in this module)

    intY = intX         'OK – intX is a module-level variable of this module

    intY = intZ         'Error – intZ is local to MySub4 

    intY = intB         'Error – intB is private to Form1

    intY = Form1.intB   'Ditto

 

End Sub

 

 

Public Sub MySub4()

 

    Dim intZ As Integer

 

    intZ = intA        'Error – qualification required

    intZ = Form1.intA  'OK – intA is public (declared in Form1)

    intZ = intW        'OK – intW is public (declared in this module)

    intZ = intX        'OK – intX is a module-level variable of this module

    intZ = intY        'Error – intY is local to MySub3

    intZ = intB        'Error – intB is private to Form1

    intZ = Form1.intB  'Ditto

 

End Sub

 

End Module