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 everythingShared
, even though you don't explicitly say so via theShared
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.