Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

vb.net

I can read a lot over the Internet that VB.Net Modules are the same thing as c#.Net Static Classes. I can also read that something close to a Static Class is a class which would look like this:

'NotInheritable so that no other class can be derived from it
Public NotInheritable Class MyAlmostStaticClass

    'Private Creator so that it cannot be instantiated
    Private Sub New()
    End Sub

    'Shared Members
    Public Shared Function MyStaticFunction() as String
        Return "Something"
    End Function

End Class

I find this code heavy to draft, and to read. I would be much more confortable just using a Module like this:

Public Module MyEquivalentStaticClass
    Public Function MyStaticFunction() as String
        Return "Something"
    End Function
End Module

However, with a Module you loose one level of Namespace hierarchy, and the following 3 statements are equal:

'Call through the Class Name is compulsory
Dim MyVar as String = Global.MyProject.MyAlmostStaticClass.MyStaticFunction()

'Call through the Module Name is OPTIONAL
Dim MyVar as String = Global.MyProject.MyEquivalentStaticClass.MyStaticFunction()
Dim MyVar as String = Global.MyProject.MyStaticFunction()

I find this very inconvenient and this either pollutes the Intelisense, or forces me to create additionnal levels of Namespace, which then means more Module declaration, i.e., more Intelisense pollution.

Is there a workaround or is this the price to pay if you want to avoid the heavy SharedMembers-NotInheritable-PrivateNew Class declaration?

Additionnal references include the very good post by Cody Gray: https://stackoverflow.com/a/39256196/10794555

like image 679
Ama Avatar asked Feb 14 '19 13:02

Ama


People also ask

What is the difference between module and class in VB net?

The main difference between classes and modules is that classes can be instantiated as objects while standard modules cannot.

What is the difference between module and class in C#?

A class is a type. You can use this type like any other type ( String , Integer , Date , FileInfo ...) to declare variables, parameters, properties, and function return types. Whereas modules are static. I.e. Data stored in a module exists exactly once.


1 Answers

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.

like image 143
Steven Doggart Avatar answered Sep 30 '22 14:09

Steven Doggart