Visual Basic Basics: Modules, Scope, and Accessibility Modifiers

Visual Basic is quite easy. It gets a lot of flack for being so easy. It makes learning the concepts of programming very simple. I used to be a programming trainer and used the BASIC language as the first stepping stone into the world of software development, and it has worked. It has worked for me, technically.

Let me tell you the boring story: I finished school back in 1996. By that time, my parents had already started a computer college. Needless to say, things were a lot different then. I didn’t want to be involved, honestly. Not having many other qualifications basically forced me into it. A few years on, I decided to venture into programming. I attempted to start with Visual C++.

It was horrible. I struggled. Add to that the fact that the book I used was literally full of errors and I had to find the errata online (with dial-up Internet). If it wasn’t for Codeguru, I would have ended up somewhere else.

I persisted, even though I had no idea what I was doing. I bought a book about Visual Basic. The language just made it simple enough for me to understand what I was doing. Only after I fully grasped Visual Basic, I could venture back to Visual C++ and understand it better. The funny part is that now I am employed as a C# developer.

Enough about me. The aim of this article is not to bore you; it is to dig into some of the intricacies of Visual Basic. Today you will learn about Scope, Modules, and Accessibility Modifiers in Visual Basic.

Scope

Scope, in programming terms, refers to the visibility of assets. These assets include variables, arrays, functions, classes, and structures. Visibility in this case means which parts of your program can see or use it.

Essentially, there are four levels of scope in Visual Basic. These are:

  • Block scope: Available only within the code block in which it is declared
  • Procedure scope: Available to all code within the procedure in which it is declared
  • Module scope: Available to all code within the module, class, or structure in which it is declared
  • Namespace scope: Available to all code in the namespace in which it is declared

Block Scope

A block is a set of statements enclosed within starting and ending declaration statements, such as the following:

  • If and End If
  • Select and End Select
  • Do and Loop
  • While and End While
  • For [Each] and Next
  • Try and End Try
  • With and End With

If you declare a variable within a block, such as the above-mentioned examples, you can use it only within that block. In the following example, the scope of the SubTotal variable is the block between the If and End If statements. Because the variable SubTotal has been declared inside the block, you cannot refer to SubTotal when execution passes out of the block.

If Tax > 15.0 Then
   Dim SubTotal As Decimal
   SubTotal = Tax * SubTotal    'Correct'
End If
'Wrong. Will Not Work Because SubTotal is Out of Scope!'
MessageBox.Show(SubTotal.ToString())

Procedure Scope

Procedure scope refers to an an element that is declared within a procedure is not available outside that procedure. Only the procedure that contains the declaration can use it. Variables at this level are usually known as local variables.

In the following example, the variable strWelcome declared in the ShowWelcome Sub procedure cannot be accessed in the Main Sub procedure:

   Sub Main()
      ShowWelcome()
      Console.WriteLine(strWelcome)    'Will not work!'
      Console.WriteLine("Press Enter to continue...")
      Console.ReadLine()
   End Sub


   Sub ShowWelcome()]
      Dim strWelcome = "Hello friend"
      Console.WriteLine(strWelcome)
   End Sub

Module Scope

You can declare elements at the Module level by placing the declaration statement outside of any procedure or block but within the module, class, or structure. When you create a variable at module level, the access level you choose determines the scope. More on Access Modifiers later.

Private elements are available to every procedure in that particular module, but not to any code in a different module.

In the following example, all procedures defined in the module can refer to the string variable strWelcome. When the second procedure is called, it displays the contents of the string variable strWelcome in a messagebox.

Private strWelcome As String   'Outside of all Procedures'
   Sub StoreWelcomeGreeting()
      strWelcome = "Welcome to the world of Programming"
   End Sub

   Sub SayWelcome()
      MessageBox.Show(strWelcome)
   End Sub

Namespace Scope

Namespace scope can be thought of as project scope. By declaring an element at module level using either the Friend or Public keyword, it becomes available to all procedures throughout the namespace in which the element is declared. An element available from within a certain namespace also is available from within any namespaces that are nested inside that namespace. Public elements in a class, module, or structure are available to any project that references their project, as well.

If I had changed the declaration of strWelcome (from the previous example) to:

Public strWelcome As String   'Outside of all Procedures'

strWelcome would have been accessible throughout the entire namespace.

Modules

A module is simply a type whose members are implicitly Shared and scoped to the declaration space of the standard module’s containing namespace. This means that the entire Namespace can access items in the Module.

Fully Qualified Names

A fully qualified name is an unambiguous name that specifies which function, object, or variable is being referred to. An object’s name is fully qualified when it includes all names in the hierarchic sequence above the given element as well as the name of the given element itself.

Members of a standard module essentially have two fully qualified names if:

  • One fully qualified name is the name without the standard module name in front.
  • One fully qualified name is one including the standard module name.

More than one module in a namespace may contain a member with the same name. Unqualified references to it outside of either module are ambiguous. For example:

Namespace Namespace1
   Module Module1
      Sub Sub1()
      End Sub
      Sub Sub2()
      End Sub
   End Module

   Module Module2
      Sub Sub2()
      End Sub
   End Module

   Module Module3
      Sub Main()
         Sub1()   'Valid - Calls Namespace1.Module1.Sub1'
         'Valid - Calls Namespace1.Module1.Sub1'
         Namespace1.Sub1()
         Sub2()              'Not valid - ambiguous'
         Namespace1.Sub2()   'Not valid - ambiguous'
         'Valid - Calls Namespace1.Module2.Sub2'
         Namespace1.Module2.Sub2()
      End Sub
   End Module
End Namespace

Differences Between Modules and Classes

The main difference between Modules and Classes is in the way they store data.

There is never more than one copy of a module’s data in memory. This means that when one part of your program changes a public object or variable in a module, and another part subsequently reads that variable, it will get the same value. Classes, on the other hand, exist separately for each instance of the class—for each object created from the class.

Another difference is that data in a module has program scope. This means that the data exists for the entire life of your program; however, class data for each instance of a class exists only for the lifetime of the object.

The last difference is that variables declared as Public in a module are visible from absolutely anywhere in the project, whereas Public variables in a class can only be accessed if you have an object variable containing a reference to a particular instance of a class.

Accessibility Modifiers

The access level of an object is what code has permission to read it or write to it. This level is determined not only by how you declare the object itself, but also by the access level of the object’s container. The keywords that specify access level are called access modifiers. Visual Basic includes five (5) Access Levels, and they are:

  • Public
  • Protected
  • Friend
  • Protected Friend
  • Private

Public

Public indicates that the objects, functions, and variables can be accessed from code anywhere in the same project, or from outside projects that reference the project, and from any assembly built from the project. The next code segment creates a Public Course Class and accesses it from somewhere else in the project:

Public Class Course
   Public CourseName As String
End Class

Public Class Student
   Public Sub Enroll()
      Dim c As New Course()
      c.CourseName = "Introduction to Programming"
   End Sub
End Class

Protected

Protected indicates that the objects, variables, and functions can be accessed only from within the same class, or from a class derived from this class. A derived class is simply a class that inherits features from another class, which is called the base class.

The following segment shows that if a class is not derived from a base class, it cannot access its members:

   Public Class Course
      Protected Duration As Integer
   End Class

   Public Class ProgrammingCourse
      Inherits Course

      Public Sub ChooseCourseDuration()
         Duration = 12   'OK'
      End Sub
   End Class

   Public Class WebDesignCourse
      Public Sub ChooseCourseDuration()
         Dim c As New Course()
         'Inaccessible Because of Protection Level'
         c.Duration = 12
      End Sub
   End Class

Friend

Friend specifies that the objects, functions, and variables can be accessed from within the same assembly, but not from outside the assembly.

Assembly 1

   Public Class Course
      Friend Cost As Double
   End Class

   Public Class GraphicDesignCourse
      Public Sub SetCost()
         Dim c As New Course()
         c.Cost = 5000   'OK'
      End Sub
   End Class

Assembly2

   Public Class BasicCourse
      Public Sub SetCost()
         Dim c As New Course()
         'Cannot Access from external Assembly'
         c.Cost = 4000
      End Sub
   End Class

Protected Friend

Protected Friend specify that objects, functions, and variables can be accessed either from derived (inherited) classes or from within the same assembly, or both.

Private

Private indicates that the objects, variables, and functions can be accessed only from within the same module, class, or structure.

Conclusion

Understanding Scope, Modules, and Access Levels is crucial in building any decent application. The sooner you know these, the better.

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read