Clases vs. módulos en VB.NET

¿Se considera una práctica aceptable utilizar Módulos en lugar de Clases con funciones de miembros Compartidos en VB.NET?

Tiendo a evitar los Módulos, porque se sienten como rests de Visual Basic 6.0 y realmente ya no parecen encajar. Por otro lado, no parece haber mucha diferencia entre usar un Módulo y una Clase con solo miembros Compartidos. No es tan frecuente que realmente necesite mucho, pero a veces hay situaciones en las que presentan una solución simple.

Tengo curiosidad por saber si tienes alguna opinión o preferencias en un sentido u otro.

Module s son equivalentes de VB a las clases static C #. Cuando su clase está diseñada únicamente para funciones auxiliares y métodos de extensión y no desea permitir la herencia y la creación de instancias , utiliza un Module .

Por cierto, usar Module no es realmente subjetivo y no está en desuso . De hecho, debe usar un Module cuando sea apropiado. .NET Framework lo hace muchas veces ( System.Linq.Enumerable , por ejemplo). Para declarar un método de extensión, se requiere el uso de Module s.

Creo que es una buena idea seguir evitando módulos a menos que los pegue en espacios de nombres separados. Porque en Intellisense, los métodos en los módulos serán visibles desde cualquier lugar en ese espacio de nombres.

Entonces, en lugar de ModuleName.MyMethod() termina con las MyMethod() emergentes de MyMethod() en cualquier lugar y esto invalida la encapsulación. (al menos en el nivel de progtwigción).

Es por eso que siempre bash crear Class con métodos compartidos, parece mucho mejor.

Los módulos no están desaprobados y se usan mucho en el lenguaje VB. Es la única forma, por ejemplo, de implementar un método de extensión en VB.Net.

Hay una gran diferencia entre los módulos y las clases con miembros estáticos. Cualquier método definido en un Módulo es accesible globalmente siempre que el Módulo esté disponible en el espacio de nombre actual. En efecto, un Módulo le permite definir métodos globales. Esto es algo que una clase con solo miembros compartidos no puede hacer.

Aquí hay un ejemplo rápido que uso mucho cuando escribo código VB que interfiere con interfaces COM sin procesar.

 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 

Es aceptable usar el Module . Module no se usa como reemplazo de la Class . Module tiene su propio propósito. El propósito del Module es usar como un contenedor para

  • métodos de extensión,
  • variables que no son específicas de ninguna Class , o
  • variables que no encajan adecuadamente en ninguna Class .

Module no es como una Class ya que no se puede

  • heredar de un Module ,
  • implementar una Interface con un Module ,
  • ni crear una instancia de un Module .

Se puede acceder directamente a cualquier cosa dentro de un Module dentro del conjunto del Module sin consultar el Module por su nombre. Por defecto, el nivel de acceso para un Module es Friend .

Clases

  • las clases se pueden instanciar como objetos
  • Los datos de objeto existen por separado para cada objeto instanciado.
  • las clases pueden implementar interfaces .
  • Los miembros definidos dentro de una clase tienen un scope dentro de una instancia específica de la clase y existen solo durante el tiempo de vida del objeto .
  • Para acceder a los miembros de la clase desde fuera de una clase, debe usar nombres completamente calificados en el formato Object.Member .

Módulos

  • Los módulos no se pueden instanciar como objetos . Debido a que solo hay una copia de los datos de un módulo estándar, cuando una parte de su progtwig cambia una variable pública en un módulo estándar, será visible para todo el progtwig.
  • Los miembros declarados dentro de un módulo son públicamente accesibles por defecto.
  • Se puede acceder mediante cualquier código que pueda acceder al módulo.
  • Esto significa que las variables en un módulo estándar son efectivamente variables globales porque son visibles desde cualquier lugar en su proyecto, y existen durante la vida del progtwig.

Cuando una de mis clases VB.NET tiene todos los miembros compartidos, la convierto en un Módulo con un espacio de nombres coincidente (o apropiado) o hago que la clase no sea heredable ni constructable:

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

Los módulos están bien para almacenar enumeraciones y algunas variables globales, constantes y funciones compartidas. es muy bueno y a menudo lo uso. Las variables declaradas son acros todo el proyecto visible.

Debe usar un Módulo (en lugar de una Clase) si está creando métodos de Extensión. En VB.NET no conozco otra opción.

Siendo resistente a los módulos, solo pasé un par de horas inútiles tratando de encontrar la forma de agregar un código repetitivo para resolver ensamblajes integrados en uno, solo para descubrir que Sub New() (Módulo) y Shared Sub New() ( Clase) son equivalentes. (¡Ni siquiera sabía que había un Sub New() invocable en un Módulo!)

Así que acabo de lanzar las líneas EmbeddedAssembly.Load y AddHandler AppDomain.CurrentDomain.AssemblyResolve ahí y Bob se convirtió en mi tío.

Adición : Todavía no lo he comprobado al 100%, pero tengo una idea de que Sub New() ejecuta en un orden diferente en un Módulo que en una Clase, simplemente por el hecho de que tuve que mover algunas declaraciones a métodos internos desde el exterior para evitar errores.