Classes et modules dans VB.NET

157

Est-il considéré comme une pratique acceptable d'utiliser des modules au lieu de classes avec des fonctions membres partagées dans VB.NET?

J'ai tendance à éviter les modules, car ils ont l'impression que les restes de Visual Basic 6.0 ne semblent plus vraiment s'intégrer. D'un autre côté, il ne semble pas y avoir beaucoup de différence entre l'utilisation d'un module et d'une classe avec uniquement des membres partagés. Ce n'est pas si souvent que j'ai vraiment besoin de l'un ou de l'autre, mais il y a parfois des situations où ils présentent une solution simple.

Je suis curieux de savoir si vous avez une opinion ou des préférences dans un sens ou dans l'autre.

Tom Juergens
la source
10
Un élément intéressant à propos des modules est que par défaut les méthodes et fonctions déclarées à l'intérieur ont le niveau de protection du module, ce qui signifie que vous pourriez par inadvertance rendre des méthodes disponibles si vous oubliez d'ajouter explicitement le Privatequalificatif. Dans une classe, le niveau de protection par défaut est privé, ce qui peut être un comportement déroutant à moins que vous n'en soyez conscient.
yu_ominae

Réponses:

207

ModuleLes s sont des équivalents VB aux staticclasses C # . Lorsque votre classe est conçue uniquement pour les fonctions d'assistance et les méthodes d'extension et que vous ne souhaitez pas autoriser l' héritage et l' instanciation , vous utilisez un Module.

Au fait, l'utilisation Modulen'est pas vraiment subjective et n'est pas obsolète . En effet, vous devez utiliser un Modulelorsque c'est approprié. .NET Framework lui-même le fait plusieurs fois ( System.Linq.Enumerablepar exemple). Pour déclarer une méthode d'extension, il est nécessaire d'utiliser Modules.

Mehrdad Afshari
la source
7
Tout à fait raison, même si je peux utiliser un constructeur privé pour empêcher l'instanciation et le modificateur NotInheritable. Légèrement plus moche qu'un simple module ancien, mais a le même effet. Merci pour le pointeur sur l'utilisation des modules dans le cadre; J'examinerai cela.
Tom Juergens
8
Sous le capot, ils sont simplement compilés en classes avec l'attribut [StandardModule]. De plus, l'utilisation de Module vous oblige à ne pas avoir de choses non partagées, ce qui est une bonne chose.
Mehrdad Afshari
18
Les modules ne sont pas les mêmes que les classes statiques en C #. Les méthodes d'un module sont effectivement globales si elles se trouvent dans un espace de noms importé.
JaredPar
2
@JaredPar: Ma formulation est probablement mauvaise. J'aurais dû dire des équivalents VB aux classes statiques C #. À partir de cette déclaration, je voulais dire que l'utilisation d'un module a du sens là où vous écririez une classe statique en C #.
Mehrdad Afshari
3
@Chiwda Voir msdn.microsoft.com/en-us/library/bb384936.aspx : "Les méthodes d'extension ne peuvent être déclarées que dans les modules."
Mehrdad Afshari
34

Je pense que c'est une bonne idée de continuer à éviter les modules à moins de les coller dans des espaces de noms séparés. Parce que dans Intellisense, les méthodes des modules seront visibles de partout dans cet espace de noms.

Donc au lieu de ModuleName.MyMethod()vous vous retrouvez avec des MyMethod()popups n'importe où et ce genre d'invalidité de l'encapsulation. (au moins au niveau de la programmation).

C'est pourquoi j'essaie toujours de créer une classe avec des méthodes partagées, cela semble tellement mieux.

dr. mal
la source
7
D'accord, je travaille actuellement sur un ancien programme (probablement un port VB6 vers VB.NET 1) avec des classes et des modules. Il y a des centaines de variables globales, de sous-marins et de fonctions dans une dizaine de modules différents, et c'est un enfer de découvrir ce qui a commencé où et comment il a été modifié.
yu_ominae
ok c'est très ancien, mais pertinent pour ma question. Je ne suis pas un gars de VB, mais je dois travailler avec. J'essaie de décomposer une grande classe (> 46 000 lignes) car IntelliSense / ReSharper vient de mourir. J'ai trouvé que l'utilisation de modules et l'extraction de gros morceaux de fonctions dans leur propre module semblent fonctionner, mais je me demande si je devrais également donner à chaque module son propre espace de noms. Serait-ce nécessaire? autrement dit, accélérerait-il IntelliSense uniquement avec les modules, ou les espaces de noms aideraient-ils davantage?
codah le
27

Les modules ne sont en aucun cas obsolètes et sont largement utilisés dans le langage VB. C'est le seul moyen par exemple d'implémenter une méthode d'extension dans VB.Net.

Il existe une énorme différence entre les modules et les classes avec des membres statiques. Toute méthode définie sur un module est globalement accessible tant que le module est disponible dans l'espace de noms actuel. En effet, un module vous permet de définir des méthodes globales. C'est quelque chose qu'une classe avec uniquement des membres partagés ne peut pas faire.

Voici un exemple rapide que j'utilise beaucoup lors de l'écriture de code VB qui interagit avec les interfaces COM brutes.

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
la source
4
Méthodes d'extension ... une autre fonctionnalité intéressante que je veux toujours utiliser, mais que je ne veux jamais vraiment utiliser - eh bien, cela me donne une autre bonne opportunité. Je connais un peu la portée mondiale, et les méthodes disponibles à l'échelle mondiale peuvent certainement être pratiques, mais je me sens un peu mal à l'aise à l'idée d'en abuser. En tout cas, toutes les réponses jusqu'à présent me disent que je ne devrais pas écarter les modules d'emblée; il y a de bonnes raisons de les utiliser dans les bonnes circonstances.
Tom Juergens
12

Il est acceptable d'utiliser Module. Modulen'est pas utilisé en remplacement de Class. Modulesert son propre objectif. Le but de Moduleest d'utiliser comme conteneur pour

  • méthodes d'extension,
  • des variables qui ne sont spécifiques à aucune Class, ou
  • variables qui ne rentrent pas correctement dans aucun Class.

Modulen'est pas comme un Classpuisque vous ne pouvez pas

  • hériter d'un Module,
  • implémenter un Interfaceavec un Module,
  • ni créer une instance d'un Module.

Tout ce qui se trouve à l'intérieur d'un Moduleest accessible directement dans l' Moduleassemblage sans faire référence au Modulepar son nom. Par défaut, le niveau d'accès pour a Moduleest Friend.

Chandra Malla
la source
11

Des classes

  • les classes peuvent être instanciées en tant qu'objets
  • Les données d'objet existent séparément pour chaque objet instancié.
  • les classes peuvent implémenter des interfaces .
  • Les membres définis dans une classe ont une portée dans une instance spécifique de la classe et n'existent que pendant la durée de vie de l'objet .
  • Pour accéder aux membres de classe depuis l'extérieur d'une classe, vous devez utiliser des noms complets au format Object.Member .

Modules

  • Les modules ne peuvent pas être instanciés en tant qu'objets , car il n'y a qu'une seule copie des données d'un module standard, lorsqu'une partie de votre programme modifie une variable publique dans un module standard, elle sera visible par l'ensemble du programme.
  • Les membres déclarés dans un module sont accessibles au public par défaut.
  • Il est accessible par n'importe quel code pouvant accéder au module.
  • Cela signifie que les variables d'un module standard sont en fait des variables globales car elles sont visibles de n'importe où dans votre projet, et elles existent pour la durée de vie du programme.
Suji
la source
6

Quand l'une de mes classes VB.NET a tous les membres partagés, je la convertis en un module avec un espace de noms correspondant (ou autrement approprié) ou je rend la classe non héritable et non constructible:

Public NotInheritable Class MyClass1

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

End Class
JRS
la source
3
Et voici la syntaxe d'un module espaces de noms: Imports <whatever>si vous avez des importations, Namespace MyCoolModule, Public Module MyCoolModule, <membres sans Shared >, End Module, End Namespace.
Rory O'Kane
0

Les modules sont parfaits pour stocker des énumérations et certaines variables globales, constantes et fonctions partagées. sa très bonne chose et je l'utilise souvent. Les variables déclarées sont visibles sur l'ensemble du projet.

GGSoft
la source
0

Vous devez utiliser un module (plutôt qu'une classe) si vous créez des méthodes d'extension. Dans VB.NET, je ne suis pas au courant d'une autre option.

Étant moi-même résistant aux modules, je viens de passer quelques heures sans valeur à essayer de trouver comment ajouter du code standard pour résoudre les assemblages intégrés en un, pour découvrir que Sub New()(Module) et Shared Sub New()(Class) sont équivalents. (Je ne savais même pas qu'il y avait un appelable Sub New()dans un module!)

Donc , je viens de jeter les EmbeddedAssembly.Loadet AddHandler AppDomain.CurrentDomain.AssemblyResolvelignes là - bas et Bob est devenu mon oncle.

Addendum : Je ne l'ai pas encore vérifié à 100%, mais j'ai une idée qui Sub New()s'exécute dans un ordre différent dans un module d'une classe, en passant simplement par le fait que j'ai dû déplacer certaines déclarations vers des méthodes internes de l'extérieur pour éviter les erreurs.

SteveCinq
la source