In Visual Basic ist der Konstruktor eine Sub New-Prozedur, die beim Erstellen einer Klasseninstanz aufgerufen wird und das Objekt initialisiert. Der Destruktor wird durch die Methode Finalize oder das Interface IDisposable (Methode Dispose) implementiert, was besonders wichtig für die Freigabe von Ressourcen ist.
Im klassischen Visual Basic wurde der Konstruktor automatisch beim Erstellen von Objekten (Class_Initialize) aufgerufen, der Destruktor beim Löschen (Class_Terminate). In VB.NET wurden überladbare Konstruktoren, die Unterscheidung zwischen der Freigabe von verwalteten und nicht verwalteten Ressourcen und die Verwendung des Garbage Collectors (GC) hinzugefügt.
Falsche Verwendung von Konstruktoren oder Destruktoren führt zu Speicherlecks, falscher Initialisierung von Objekten oder Blockierung von Ressourcen (z.B. Dateien).
Verwenden Sie Sub New zur Initialisierung von Objekten und implementieren Sie unbedingt Dispose zur expliziten Freigabe von Ressourcen. Wenn ein Destruktor (Finalize) verwendet wird, denken Sie an die Latenz des GC und die Unmöglichkeit, den Zeitpunkt des Aufrufs vorherzusagen.
Beispielcode:
Public Class ResourceHolder Implements IDisposable Private resource As SomeResource Public Sub New() resource = New SomeResource() Console.WriteLine("Ressource zugewiesen") End Sub Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overridable Sub Dispose(disposing As Boolean) If disposing Then If resource IsNot Nothing Then resource.Release() resource = Nothing End If End If End Sub End Class
Wichtige Besonderheiten:
Kann man den Konstruktor Sub New manuell für ein bereits vorhandenes Objekt aufrufen?
Nein, der Konstruktor wird nur beim Erstellen eines Objekts aufgerufen. Für eine erneute Initialisierung verwenden Sie eine separate Methode Reset oder ähnlich.
Wann wird Finalize aufgerufen und ist seine Ausführung immer garantiert?
Finalize wird vom Garbage Collector beim Zerstören des Objekts aufgerufen, aber seine Ausführung ist nicht garantiert (z.B. bei einem plötzlichen Prozessabbruch oder Stromausfall).
Warum sollte man GC.SuppressFinalize innerhalb von Dispose aufrufen?
Das verhindert einen erneuten Aufruf von Finalize für bereits manuell freigegebene Objekte, erhöht die Performance und verhindert Speicherlecks.
Im Projekt wurde Dispose nicht implementiert, und mehrere Dateien blieben nach dem Beenden der Anwendung gesperrt — Ressourcen wurden erst nach Eingriff des Garbage Collectors freigegeben.
Vorteile:
Nachteile:
Es wurde IDisposable und Dispose implementiert, und es wurde Using bei der Arbeit mit externen Ressourcen verwendet. Alle Dateien werden korrekt geschlossen, und die Anwendung arbeitet stabil.
Vorteile:
Nachteile: