Modules, Structures, and Classes

Application Organization 101 - The Basics

Businesswoman typing on computer keyboard
Siri Stafford/Digital Vision/Getty Images

There are just three ways to organize a VB.NET application.

  • Modules
  • Structures
  • Classes

But most technical articles assume that you already know all about them. If you're one of the many who still have a few questions, you could just read past the confusing bits and try to figure it out anyway. And if you have a lot of time, you can start searching through Microsoft's documentation:

  • "A Module is a portable executable file, such as type.dll or application.exe, consisting of one or more classes and interfaces."
  • "A Class statement defines a new data type."
  • "The Structure statement defines a composite value type that you can customize."

Right, then. Any questions?

To be a bit more fair to Microsoft, they have pages and pages (and more pages) of information about all of these that you can wade through. And they have to be as exact as possible because they set the standard. In other words, Microsoft's documentation sometimes reads like a law book because it is a law book.

But if you're just learning .NET, it can be very confusing! You have to start somewhere. Understanding the three fundamental ways that you can write code in VB.NET is a good place to start.

You can write VB.NET code using any of these three forms. In other words, you can create a Console Application in VB.NET Express and write:

Module Module1
   Sub Main()
      MsgBox("This is a Module!")
   End Sub
End Module
Class Class1
   Sub Main()
      MsgBox("This is a Class")
   End Sub
End Class
Structure Struct1
   Dim myString As String
   Sub Main()
      MsgBox("This is a Structure")
   End Sub
End Structure

This doesn't make any sense as a program, of course. The point is that you don't get a syntax error so it's "legal" VB.NET code.

These three forms are the only way to code the queen bee root of all of .NET: the object. The only element that interrupts the symmetry of the three forms is the statement: Dim myString As String.

That has to do with a Structure being a "composite data type" as Microsoft states in their definition.

Another thing to notice is that all three blocks have a Sub Main() in them. One of the most fundamental principals of OOP is usually called encapsulation. (See my discussion of OOP and encapsulation by clicking here.) This is the "black box" effect. In other words, you should be able to treat each object independently and that includes using identically named subroutines if you want to.

On the next page, we dive into the most important object form, the Class, and also the Module.

Classes

Classes are the 'right' place to start because, as Microsoft notes, "A class is a fundamental building block of object-oriented programming (OOP)." In fact, some authors treat modules and structures as just special kinds of classes. A class is more object oriented than a module because it's possible to instantiate (make a copy of) a class but not a module.

In other words, you can code ...

Public Class Form1
   Private Sub Form1_Load( _
      ByVal sender As System.Object, _
      ByVal e As System.EventArgs) _
      Handles MyBase.Load
      Dim myNewClass As Class1 = New Class1
      myNewClass.ClassSub()
   End Sub
End Class

(The class instantiation is emphasized.)

It doesn't matter whether the actual class itself, in this case, ...

Public Class Class1
   Sub ClassSub()
      MsgBox("This is a class")
   End Sub
End Class

... is in a file by itself or is part of the same file with the Form1 code. The program runs exactly the same way. (Notice that Form1 is a class too.)

You can also write class code that behaves much like a module, that is, without instantiating it. This is called a Shared class. The article "Static" (that is, "Shared") versus Dynamic Types in VB.NET explains this in much more detail.

Another fact about classes should also be kept in mind. Members (properties and methods) of the class only exist while the instance of the class exists. The name for this is scoping. That is, the scope of an instance of a class is limited. The code above can be changed to illustrate this point this way:

Public Class Form1
   Private Sub Form1_Load( _
      ByVal sender As System.Object, _
      ByVal e As System.EventArgs) _
      Handles MyBase.Load
      Dim myNewClass As Class1 = New Class1
      myNewClass.ClassSub()
      myNewClass = Nothing
      myNewClass.ClassSub()
   End Sub
End Class

When the second myNewClass.ClassSub() statement is executed, a NullReferenceException error is thrown because the ClassSub member doesn't exist.

Modules

In VB 6, it was common to see programs where most of the code was in a module (A .BAS, file rather than, for instance, in a Form file such as Form1.frm.) In VB.NET, both modules and classes are in .VB files.

The main reason modules are included in VB.NET is to give programmers a way to organize their systems by putting code in different places to fine tune the scope and access for their code. (That is, how long members of the module exist and what other code can reference and use the members.) Sometimes, you may want to put code into separate modules just to make it easier to work with.

All VB.NET modules are Shared because they can't be instantiated (see above) and they can be marked Friend or Public so they can be accessed either within the same assembly or whenever they're referenced.

Are Structures another type of object? Find out on the next page.

Structures

Structures are the least understood of the three forms of objects. If we were talking about "animals" instead of "objects", the structure would be an Aardvark.

The big difference between a structure and a class is that a structure is a value type and a class is a reference type.

What does that mean? I'm so glad you asked.

A value type is an object that is stored directly in memory. An Integer is a good example of a value type.

If you declared an Integer in your program like this ...

Dim myInt as Integer = 10

... and you checked the memory location stored in myInt, you would find the value 10. You also see this described as "being allocated on the stack".

The stack and the heap are simply different ways of managing the use of computer memory.

A reference type is an object where the location of the object is stored in memory. So finding a value for a reference type is always a two step lookup. A String is a good example of a reference type. If you declared a String like this ...

Dim myString as String = "This is myString"

... and you checked the memory location stored in myString, you would find another memory location (called a pointer - this way of doing things is the very heart of C style languages). You would have to go to that location to find the value "This is myString". This is often called "being allocated on the heap".

The stack and the heap

Some authors say that value types aren't even objects and only reference types can be objects. It's certainly true that the sophisticated object characteristics like inheritance and encapsulation are only possible with reference types. But we started this whole article by saying that there were three forms for objects so I have to accept that structures are some sort of object, even if they're non-standard objects.

The programming origins of structures go back to file-oriented languages like Cobol. In those languages, data was normally processed as sequential flat files. The "fields" in a record from the file were described by a "data definition" section (sometimes called a "record layout" or a "copybook"). So, if a record from the file contained:

1234567890ABCDEF9876

The only way you would know that "1234567890" was a phone number, "ABCDEF" was an ID and 9876 was $98.76 was through the data definition. Structures help you accomplish this in VB.NET.

Structure Structure1
   <VBFixedString(10)> Dim myPhone As String
   <VBFixedString(6)> Dim myID As String
   <VBFixedString(4)> Dim myAmount As String
End Structure

Because a String is a reference type, it's necessary to keep the length the same with the VBFixedString attribute for fixed length records. You can find an extended explanation of this attribute and attributes in general in the article Attributes in VB .NET.

Although structures are non-standard objects, they do have a lot of capability in VB.NET. You can code methods, properties, and even events, and event handlers in structures, but you can also use more simplified code and because they're value types, processing can be faster.

For example, you could recode the structure above like this:

Structure Structure1
   <VBFixedString(10)> Dim myPhone As String
   <VBFixedString(6)> Dim myID As String
   <VBFixedString(4)> Dim myAmount As String
   Sub mySub()
      MsgBox("This is the value of myPhone: " & myPhone)
   End Sub
End Structure

And use it like this:

Dim myStruct As Structure1
myStruct.myPhone = "7894560123"
myStruct.mySub()

It's worth your time to play around with structures a bit and learn what they can do. They're one of the odd corners of VB.NET that can be a magic bullet when you need it.