Is a Module really identical to a SharedMembers-NotInheritable-PrivateNew Class?

No, there is no exact equivalent to a C# static class in VB.NET. It would be nice if VB had the ability to add the Shared modifier to a class declaration, like this:

Public Shared Class Test  ' This won't work, so don't try it
    ' Compiler only allows shared members in here
End Class

But, unfortunately, it does not. If you do that, the compiler gives you the following error:

Classes cannot be declared 'Shared'

That leaves us with the two options you listed:

  • Either you make a non-instantiable class containing only Shared members (without the safety of that rule being enforced by the compiler), or
  • Use a Module, which makes everything Shared, even though you don't explicitly say so via the Shared modifier

As you said, many people don't like the loss of the class name being required, as a sort-of extra namespace layer, so they prefer the Class with only Shared members over the Module. But, that's a matter of preference.

It's worth noting that, while you don't have to specify the module name everywhere you call its members, you can always do so if you wish:

MyModule.MyMethod()

While a "SharedMembers-NotInheritable-PrivateNew Class", as you so eloquently called it, is the closest approximation to a static class, it's only functionally equivalent. If you use reflection, you'll see that the attributes of the type are not the same. For instance, in VB:

Module MyModule
    Public Sub Main()
        Dim t As Type = GetType(MyClass)
    End Sub
End Module

Public NotInheritable Class MyClass
    Private Sub New()
    End Sub

    Public Shared Sub MyMethod()
    End Sub
End Class

If you take a look at t.Attributes, you'll see that it equals Public Or Sealed. So the MyClass type is both sealed (NotInheritable) and public. However, if you do this in C#:

class Program
{
    static void Main(string[] args)
    {
        Type t = typeof(Test);
    }
}

public static class MyClass
{
    public static void MyMethod()
    { }
}

And you inspect the t.Attributes again, this time, the value is Public | Abstract | Sealed | BeforeFieldInit. That's not the same. Since you can't declare a class in VB as both NotInheritable and MustInherit at the same time, you have no chance of exactly duplicating that thing. So, while they more-or-less are equivalent, the attributes of the types are different. Now, just for fun, let's try this:

Module MyModule
    Public Sub Main()
        Dim t As Type = GetType(MyModule)
    End Sub
End Module

Now, the t.Attributes for the module are Sealed. That's it. Just Sealed. So that's not the same either. The only way to get a true static class in VB (meaning, the type has the same attributes when inspected via reflection) is to write it in a C# class library, and then reference the library in VB.

Tags:

Vb.Net