Clases frente a módulos en VB.NET

157

¿Se considera una práctica aceptable usar módulos en lugar de clases con funciones de miembro compartidas en VB.NET?

Tiendo a evitar los módulos, porque sienten que quedan restos 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 tenga mucha necesidad, pero a veces hay situaciones en las que presentan una solución simple.

Tengo curiosidad por saber si tienes alguna opinión o preferencia de una forma u otra.

Tom Juergens
fuente
10
Un aspecto interesante acerca de los módulos es que, de forma predeterminada, los métodos y funciones declarados en el interior tienen el nivel de protección del módulo, lo que significa que puede hacer que los métodos estén disponibles sin darse cuenta si olvida agregar explícitamente el Privatecalificador. En una clase, el nivel de protección predeterminado es privado, lo que puede ser un comportamiento confuso a menos que lo sepa.
yu_ominae

Respuestas:

207

Modules son contrapartes de VB para las staticclases de C # . Cuando su clase está diseñada exclusivamente para funciones auxiliares y métodos de extensión y no desea permitir la herencia y la creación de instancias , utiliza a Module.

Por cierto, el uso Moduleno es realmente subjetivo y no está en desuso . De hecho, debe usar un Modulecuando sea apropiado. .NET Framework lo hace muchas veces ( System.Linq.Enumerablepor ejemplo). Para declarar un método de extensión, es necesario usar Modules.

Mehrdad Afshari
fuente
77
Muy bien, aunque puedo usar un constructor privado para evitar la creación de instancias y el modificador NotInheritable. Ligeramente más feo que un módulo antiguo simple, pero tiene el mismo efecto. Gracias por el puntero al uso de Módulos en el Marco; Lo investigaré.
Tom Juergens
8
Bajo el capó, simplemente se compilan en clases con el atributo [StandardModule]. Además, el uso del Módulo te obliga a no tener cosas no compartidas allí, lo cual es algo bueno.
Mehrdad Afshari
18
Los módulos no son lo mismo que las clases estáticas en C #. Los métodos en un módulo son efectivamente globales si están en un espacio de nombres importado.
JaredPar
2
@JaredPar: Mi redacción es probablemente mala. Debería haber dicho contrapartes de VB a las clases estáticas de C #. A partir de esa declaración, quise decir que usar un Módulo tiene sentido donde escribirías una clase estática en C #.
Mehrdad Afshari
3
@Chiwda Consulte msdn.microsoft.com/en-us/library/bb384936.aspx : "Los métodos de extensión solo pueden declararse dentro de los módulos".
Mehrdad Afshari
34

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 todas partes en ese espacio de nombres.

Entonces, en lugar de ModuleName.MyMethod()terminar con MyMethod()ventanas emergentes en cualquier lugar, esto invalida la encapsulación. (al menos en el nivel de programación).

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

Dr. mal
fuente
77
De acuerdo, estoy trabajando en un programa antiguo en este momento (probablemente un puerto VB6 a VB.NET 1) con clases y módulos. Hay cientos de variables globales, subs y funciones en aproximadamente diez módulos diferentes, y es un infierno descubrir qué se originó, dónde y cómo se modificó.
yu_ominae
ok esto es muy antiguo, pero relevante para mi pregunta. Estoy no un tipo VB, pero tengo que trabajar con él. Estoy tratando de dividir una clase grande (> 46,000 líneas) porque IntelliSense / ReSharper simplemente muere. Descubrí que usar Módulos y simplemente extraer grandes fragmentos de funciones en su propio Módulo parece funcionar, pero me pregunto si debería darle a cada módulo su propio espacio de nombres también. ¿Sería eso necesario? es decir, ¿aceleraría IntelliSense solo con los módulos, o los espacios de nombres ayudarían más?
codah
27

Los módulos de ninguna manera están en desuso 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 módulos y 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 nombres 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 interopera 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
JaredPar
fuente
44
Métodos de extensión ... otra buena característica que siempre pretendo usar, pero que realmente nunca uso, bueno, esto me da otra buena oportunidad. Sí entiendo el alcance global, y los métodos disponibles a nivel mundial ciertamente pueden ser convenientes, pero me siento un poco mareado por usarlos en exceso. En cualquier caso, todas las respuestas hasta ahora me dicen que no debería descartar los módulos de inmediato; Hay buenas razones para usarlos en las circunstancias correctas.
Tom Juergens
12

Es aceptable de usar Module. Moduleno se utiliza como un reemplazo para Class. Modulecumple su propio propósito. El propósito de Modulees usarlo como contenedor para

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

Moduleno es como un Classya que no puedes

  • heredar de a Module,
  • implementar un Interfacecon un Module,
  • ni crear una instancia de a Module.

ModuleSe puede acceder directamente a cualquier cosa dentro de a dentro del Moduleensamblaje sin hacer referencia al Modulenombre. Por defecto, el nivel de acceso para a Modulees Friend.

Chandra Malla
fuente
11

Clases

  • las clases pueden ser instanciadas como objetos
  • Los datos del objeto existen por separado para cada objeto instanciado.
  • Las clases pueden implementar interfaces .
  • Los miembros definidos dentro de una clase tienen un alcance dentro de una instancia específica de la clase y existen solo durante la vida útil del objeto .
  • Para acceder a los miembros de la clase desde fuera de una clase, debe usar nombres completos en el formato de Object.Member .

Módulos

  • Los módulos no pueden ser instanciados como objetos , ya que solo hay una copia de los datos de un módulo estándar, cuando una parte de su programa cambia una variable pública en un módulo estándar, será visible para todo el programa.
  • Los miembros declarados dentro de un módulo son de acceso público de forma predeterminada.
  • 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 parte de su proyecto y existen durante toda la vida del programa.
Suji
fuente
6

Cuando una de mis clases de 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 y no construible:

Public NotInheritable Class MyClass1

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

End Class
JRS
fuente
3
Y aquí está la sintaxis de un módulo de espacio de nombres: Imports <whatever>si tiene cualquier importación, Namespace MyCoolModule, Public Module MyCoolModule, <miembros sin Shared >, End Module, End Namespace.
Rory O'Kane
0

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

GGSoft
fuente
0

Usted debe utilizar un módulo (en lugar de una clase) si va a crear métodos de extensión. En VB.NET no conozco otra opción.

Siendo resistente a los módulos, pasé un par de inútiles horas tratando de encontrar la manera de agregar un código repetitivo para resolver los ensamblados integrados en uno, solo para descubrir que Sub New()(Módulo) y Shared Sub New()(Clase) son equivalentes. (Ni siquiera sé que era un exigible Sub New()en un módulo!)

Así que acaba de lanzar el EmbeddedAssembly.Loady AddHandler AppDomain.CurrentDomain.AssemblyResolvelíneas de allí y Bob se convirtió en mi tío.

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

SteveCinq
fuente