Klassen vs. Module in VB.NET

157

Wird es als akzeptabel angesehen, in VB.NET Module anstelle von Klassen mit gemeinsam genutzten Elementfunktionen zu verwenden?

Ich neige dazu, Module zu meiden, weil sie das Gefühl haben, Reste von Visual Basic 6.0 zu haben und nicht mehr wirklich zu passen. Andererseits scheint es keinen großen Unterschied zwischen der Verwendung eines Moduls und einer Klasse mit nur gemeinsam genutzten Mitgliedern zu geben. Es ist nicht so oft, dass ich wirklich viel Bedarf habe, aber manchmal gibt es Situationen, in denen sie eine einfache Lösung darstellen.

Ich bin gespannt, ob Sie auf die eine oder andere Weise eine Meinung oder Vorlieben haben.

Tom Jürgens
quelle
10
Ein interessantes Merkmal von Modulen ist, dass die darin deklarierten Methoden und Funktionen standardmäßig die Schutzstufe des Moduls haben. Dies bedeutet, dass Sie versehentlich Methoden zur Verfügung stellen können, wenn Sie vergessen, das PrivateQualifikationsmerkmal explizit hinzuzufügen . In einer Klasse ist die Standardschutzstufe privat. Dies kann verwirrendes Verhalten sein, sofern Sie sich dessen nicht bewusst sind.
Yu_ominae

Antworten:

207

Modules sind VB-Gegenstücke zu C # static-Klassen. Wenn Ihre Klasse ausschließlich für Hilfsfunktionen und Erweiterungsmethoden konzipiert ist und Sie keine Vererbung und Instanziierung zulassen möchten , verwenden Sie aModule .

Übrigens ist die Verwendung Modulenicht wirklich subjektiv und nicht veraltet . In der Tat müssen Sie ein verwenden, Modulewenn es angemessen ist. .NET Framework selbst macht das viele Male ( System.Linq.Enumerablezum Beispiel). Um eine Erweiterungsmethode zu deklarieren, muss Modules verwendet werden.

Mehrdad Afshari
quelle
7
Ganz richtig, obwohl ich einen privaten Konstruktor verwenden kann, um die Instanziierung und den Modifikator NotInheritable zu verhindern. Etwas hässlicher als ein einfaches altes Modul, hat aber den gleichen Effekt. Vielen Dank für den Hinweis auf die Verwendung von Modulen im Framework. Ich werde das untersuchen.
Tom Juergens
8
Unter der Haube werden sie nur zu Klassen mit dem Attribut [StandardModule] kompiliert. Wenn Sie Module verwenden, müssen Sie dort keine nicht freigegebenen Dinge haben, was eine gute Sache ist.
Mehrdad Afshari
18
Module sind nicht mit statischen Klassen in C # identisch. Methoden in einem Modul sind effektiv global, wenn sie sich in einem importierten Namespace befinden.
JaredPar
2
@ JaredPar: Mein Wortlaut ist wahrscheinlich schlecht. Ich hätte VB-Gegenstücke zu statischen C # -Klassen sagen sollen. Aufgrund dieser Aussage wollte ich sagen, dass die Verwendung eines Moduls sinnvoll ist, wenn Sie eine statische Klasse in C # schreiben würden.
Mehrdad Afshari
3
@Chiwda Siehe msdn.microsoft.com/en-us/library/bb384936.aspx : "Erweiterungsmethoden können nur innerhalb von Modulen deklariert werden."
Mehrdad Afshari
34

Ich denke, es ist eine gute Idee, Module weiterhin zu vermeiden, es sei denn, Sie stecken sie in separate Namespaces. Denn in Intellisense sind Methoden in Modulen von überall in diesem Namespace sichtbar.

Anstatt dass ModuleName.MyMethod()Sie MyMethod()irgendwo Popups haben, macht diese Art der Kapselung ungültig. (zumindest in der Programmierebene).

Deshalb versuche ich immer, eine Klasse mit gemeinsamen Methoden zu erstellen, scheint so viel besser zu sein.

DR. böse
quelle
6
Einverstanden, ich arbeite gerade an einem alten Programm (wahrscheinlich einem VB6-zu-VB.NET 1-Port) mit Klassen und Modulen. Es gibt Hunderte von globalen Variablen, Subs und Funktionen in ungefähr zehn verschiedenen Modulen, und es ist verdammt herauszufinden, was wo entstanden ist und wie es geändert wurde.
yu_ominae
ok das ist sehr alt, aber relevant für meine frage. Ich bin kein VB-Typ, aber ich muss damit arbeiten. Ich versuche, eine große Klasse (> 46.000 Zeilen) aufzubrechen, weil IntelliSense / ReSharper einfach sterben. Ich habe festgestellt, dass die Verwendung von Modulen und das Herausreißen großer Funktionsblöcke in ein eigenes Modul zu funktionieren scheint, aber ich frage mich, ob ich jedem Modul auch einen eigenen Namespace geben soll. Wäre das notwendig? dh würde es IntelliSense nur mit den Modulen beschleunigen, oder würden Namespaces mehr helfen?
Codah
27

Module sind keineswegs veraltet und werden in der VB-Sprache häufig verwendet. Dies ist beispielsweise die einzige Möglichkeit, eine Erweiterungsmethode in VB.Net zu implementieren.

Es gibt einen großen Unterschied zwischen Modulen und Klassen mit statischen Elementen. Auf jede in einem Modul definierte Methode kann global zugegriffen werden, solange das Modul im aktuellen Namespace verfügbar ist. In einem Modul können Sie tatsächlich globale Methoden definieren. Dies kann eine Klasse mit nur gemeinsam genutzten Mitgliedern nicht.

Hier ist ein kurzes Beispiel, das ich häufig beim Schreiben von VB-Code verwende, der mit unformatierten COM-Schnittstellen zusammenarbeitet.

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
quelle
4
Erweiterungsmethoden ... eine weitere gute Funktion, die ich immer verwenden möchte, aber nie wirklich verstehe - nun, das gibt mir eine weitere gute Gelegenheit. Ich verstehe den globalen Geltungsbereich, und global verfügbare Methoden können sicherlich praktisch sein, aber ich fühle mich ein bisschen unwohl, wenn ich sie übermäßig benutze. Auf jeden Fall sagen mir alle bisherigen Antworten, dass ich Module nicht sofort abweisen sollte; Es gibt gute Gründe, sie unter den richtigen Umständen einzusetzen.
Tom Juergens
12

Es ist akzeptabel zu verwenden Module. Modulewird nicht als Ersatz für verwendet Class. Moduledient seinem eigenen Zweck. Der Zweck von Moduleist als Behälter für zu verwenden

  • Erweiterungsmethoden,
  • Variablen, die für keine spezifisch sind Class, oder
  • Variablen, die in keine passen Class.

Moduleist nicht wie ein Classda kannst du nicht

  • erben von a Module,
  • implementieren ein Interfacemit a Module,
  • noch erstellen Sie eine Instanz von a Module.

Auf alles in einem Modulekann direkt innerhalb der ModuleBaugruppe zugegriffen werden, ohne auf den ModuleNamen zu verweisen . Standardmäßig wird die Zugriffsebene für einen Moduleist Friend.

Chandra Malla
quelle
11

Klassen

  • Klassen können als Objekte instanziiert werden
  • Objektdaten sind für jedes instanziierte Objekt separat vorhanden.
  • Klassen können Schnittstellen implementieren .
  • Innerhalb einer Klasse definierte Mitglieder haben einen Gültigkeitsbereich innerhalb einer bestimmten Instanz der Klasse und sind nur für die Lebensdauer des Objekts vorhanden .
  • Um von außerhalb einer Klasse auf Klassenmitglieder zuzugreifen, müssen Sie vollständig qualifizierte Namen im Format Object.Member verwenden .

Module

  • Module können nicht als Objekte instanziiert werden . Da es nur eine Kopie der Daten eines Standardmoduls gibt, ist diese für das gesamte Programm sichtbar, wenn ein Teil Ihres Programms eine öffentliche Variable in einem Standardmodul ändert.
  • Innerhalb eines Moduls deklarierte Mitglieder sind öffentlich zugänglich standardmäßig .
  • Auf jeden Code kann zugegriffen werden, der auf das Modul zugreifen kann.
  • Dies bedeutet, dass Variablen in einem Standardmodul effektiv globale Variablen sind, da sie von überall in Ihrem Projekt sichtbar sind und für die gesamte Laufzeit des Programms vorhanden sind.
Suji
quelle
6

Wenn eine meiner VB.NET-Klassen alle gemeinsam genutzten Mitglieder hat, konvertiere ich sie entweder in ein Modul mit einem passenden (oder anderweitig geeigneten) Namespace oder mache die Klasse nicht vererbbar und nicht konstruierbar:

Public NotInheritable Class MyClass1

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

End Class
JRS
quelle
3
Und hier ist die Syntax für ein Namespace - Modul: Imports <whatever>Wenn Sie irgendwelche Importe Namespace MyCoolModule, Public Module MyCoolModule<Mitglieder ohne Shared >, End Module, End Namespace.
Rory O'Kane
0

Module eignen sich gut zum Speichern von Aufzählungen und einigen globalen Variablen, Konstanten und gemeinsam genutzten Funktionen. Es ist sehr gut und ich benutze es oft. Deklarierte Variablen sind im gesamten Projekt sichtbar.

GGSoft
quelle
0

Sie müssen ein Modul (anstelle einer Klasse) verwenden, wenn Sie Erweiterungsmethoden erstellen. In VB.NET ist mir keine andere Option bekannt.

Da ich selbst gegen Module resistent bin, habe ich nur ein paar Stunden lang wertlos versucht, herauszufinden, wie man Boilerplate-Code hinzufügt, um eingebettete Assemblys in einer aufzulösen, nur um herauszufinden, dass Sub New()(Module) und Shared Sub New()(Class) gleichwertig sind. (Ich wusste nicht einmal, dass es das gab eine aufrufbare Sub New()in einem Modul!)

Also warf ich einfach die EmbeddedAssembly.Loadund AddHandler AppDomain.CurrentDomain.AssemblyResolveZeilen hinein und Bob wurde mein Onkel.

Nachtrag : Ich habe es noch nicht zu 100% ausgecheckt, aber ich habe eine Ahnung, Sub New()die in einem Modul in einer anderen Reihenfolge als in einer Klasse ausgeführt wird, nur weil ich einige Deklarationen von außen auf interne Methoden verschieben musste, um dies zu vermeiden Fehler.

SteveCinq
quelle