171

Is it considered an acceptable practice to use Modules instead of Classes with Shared member functions in VB.NET?

I tend to avoid Modules, because they feel like leftover remains from Visual Basic 6.0 and don't really seem to fit in anymore. On the other hand, there doesn't seem to be much difference between using a Module and a Class with only Shared members. It's not that often that I really have much need for either, but sometimes there are situations where they present a simple solution.

I'm curious to hear whether you have any opinion or preferences one way or the other.

2
  • 11
    One interesting about modules is that by default the methods and functions declared inside have the protection level of the module, which means you could inadvertently make methods available if you forget to explicitly add the Private qualifier. In a class, the default protection level is private, which can be confusing behaviour unless you are aware about it.
    – yu_ominae
    Dec 18, 2012 at 6:53
  • I AM SO THANKFUL TO HAVE FOUND THIS! I've been wracking my brain to find out how Intellisense can pickup on so many other Methods and such without instantiating the classes explicitly as I'm developing several classes that I though should be global, and having more experience with VBA's Global attribute, I'm ecstatic to find out that Modules are indeed exactly what I am looking for.
    – k1dfr0std
    Jul 17, 2022 at 8:06

8 Answers 8

226

Modules are VB counterparts to C# static classes. When your class is designed solely for helper functions and extension methods and you don't want to allow inheritance and instantiation, you use a Module.

By the way, using Module is not really subjective and it's not deprecated. Indeed you must use a Module when it's appropriate. .NET Framework itself does it many times (System.Linq.Enumerable, for instance). To declare an extension method, it's required to use Modules.

6
  • 7
    Quite right, although I can use a private constructor to prevent instantiation and the NotInheritable modifier. Slightly uglier than a plain old Module, but has the same effect. Thanks for the pointer to the use of Modules in the Framework; I'll look into that. May 19, 2009 at 8:41
  • 8
    Under the hood, they are just compiled to classes with [StandardModule] attribute. Also, using Module forces you not to have non-Shared things there which is a good thing. May 19, 2009 at 8:47
  • 20
    Modules are not the same as static classes in C#. Methods in a module are effectively global if they are in an imported namespace.
    – JaredPar
    May 19, 2009 at 14:16
  • 2
    @JaredPar: My wording is probably bad. I should have said VB counterparts to C# static classes. From that statement, I meant to say using a Module makes sense where you'd write a static class in C#. May 19, 2009 at 14:26
  • 3
    @Chiwda See msdn.microsoft.com/en-us/library/bb384936.aspx : "Extension methods can be declared only within modules." Aug 20, 2012 at 4:56
37

I think it's a good idea to keep avoiding modules unless you stick them into separate namespaces. Because in Intellisense methods in modules will be visible from everywhere in that namespace.

So instead of ModuleName.MyMethod() you end up with MyMethod() popups in anywhere and this kind of invalidates the encapsulation. (at least in the programming level).

That's why I always try to create Class with shared methods, seems so much better.

2
  • 7
    Agreed, I am working on an old program at the moment (probably a VB6 to VB.NET 1 port) with classes and modules. There are hundreds of global variables, subs and functions in about ten different modules, and it is hell finding out what originated where and how it got modified.
    – yu_ominae
    Dec 18, 2012 at 6:32
  • ok this is very old, but relevant to my question. I'm not a VB guy, but I have to work with it. I'm trying to break down a big class (>46,000 lines) because IntelliSense/ReSharper just die. I've found using Modules and just ripping out large chunks of functions into their own Module seems to work, but I'm wondering if I should give each module its own namespace as well. Would that be necessary? i.e. would it speed up IntelliSense just with the Modules, or would Namespaces help more?
    – codah
    Jul 13, 2020 at 23:40
28

Modules are by no means deprecated and are used heavily in the VB language. It's the only way for instance to implement an extension method in VB.Net.

There is one huge difference between Modules and Classes with Static Members. Any method defined on a Module is globally accessible as long as the Module is available in the current namespace. In effect a Module allows you to define global methods. This is something that a class with only shared members cannot do.

Here's a quick example that I use a lot when writing VB code that interops with raw COM interfaces.

Module Interop
  Public Function Succeeded(ByVal hr as Integer) As Boolean
    ...
  End Function

  Public Function Failed(ByVal hr As Integer) As Boolean
    ...
  End Function
End Module

Class SomeClass
  Sub Foo()
    Dim hr = CallSomeHrMethod()
    if Succeeded(hr) then
      ..
    End If
  End Sub
End Class
1
  • 4
    Extension methods... another fine feature I always mean to use, but never really get around to - well, this gives me another good opportunity. I do get the bit about global scope, and globally available methods can certainly be convenient, but I feel a bit queasy about overusing them. At any rate, all of the answers so far tell me that I shouldn't dismiss modules out of hand; there are good reasons to use them in the right circumstances. May 19, 2009 at 16:28
12

It is acceptable to use Module. Module is not used as a replacement for Class. Module serves its own purpose. The purpose of Module is to use as a container for

  • extension methods,
  • variables that are not specific to any Class, or
  • variables that do not fit properly in any Class.

Module is not like a Class since you cannot

  • inherit from a Module,
  • implement an Interface with a Module,
  • nor create an instance of a Module.

Anything inside a Module can be directly accessed within the Module assembly without referring to the Module by its name. By default, the access level for a Module is Friend.

11

Classes

  • classes can be instantiated as objects
  • Object data exists separately for each instantiated object.
  • classes can implement interfaces.
  • Members defined within a class are scoped within a specific instance of the class and exist only for the lifetime of the object.
  • To access class members from outside a class, you must use fully qualified names in the format of Object.Member.

Modules

  • Modules cannot be instantiated as objects,Because there is only one copy of a standard module's data, when one part of your program changes a public variable in a standard module, it will be visible to the entire program.
  • Members declared within a module are publicly accessible by default.
  • It can be accessed by any code that can access the module.
  • This means that variables in a standard module are effectively global variables because they are visible from anywhere in your project, and they exist for the life of the program.
6

When one of my VB.NET classes has all shared members I either convert it to a Module with a matching (or otherwise appropriate) namespace or I make the class not inheritable and not constructable:

Public NotInheritable Class MyClass1

   Private Sub New()
      'Contains only shared members.
      'Private constructor means the class cannot be instantiated.
   End Sub

End Class
1
  • 3
    And here's the syntax for a namespaced module: Imports <whatever> if you have any imports, Namespace MyCoolModule, Public Module MyCoolModule, <members without Shared>, End Module, End Namespace. Apr 29, 2013 at 15:24
0

Modules are fine for storing enums and some global variables, constants and shared functions. its very good thing and I often use it. Declared variables are visible acros entire project.

0

You must use a Module (rather than a Class) if you're creating Extension methods. In VB.NET I'm not aware of another option.

Being resistant to Modules myself, I just spent a worthless couple of hours trying to work out how to add some boilerplate code to resolve embedded assemblies in one, only to find out that Sub New() (Module) and Shared Sub New() (Class) are equivalent. (I didn't even know there was a callable Sub New() in a Module!)

So I just threw the EmbeddedAssembly.Load and AddHandler AppDomain.CurrentDomain.AssemblyResolve lines in there and Bob became my uncle.

Addendum: I haven't checked it out 100% yet, but I have an inkling that Sub New() runs in a different order in a Module than a Class, just going by the fact that I had to move some declarations to inside methods from outside to avoid errors.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.