Objektlebensdauer: Erstellen und Zerstören von Objekten

Aktualisiert: November 2007

Eine Instanz einer Klasse, ein Objekt, wird mit dem New-Schlüsselwort erstellt. Häufig müssen Initialisierungsaufgaben für neue Objekte ausgeführt werden, bevor sie verwendet werden. Zu den allgemeinen Initialisierungsaufgaben zählen das Öffnen von Dateien, das Herstellen von Verbindungen mit Datenbanken und das Lesen von Registrierungsschlüsselwerten. Visual Basic steuert die Initialisierung neuer Objekte mit Prozeduren, die als Konstruktoren bezeichnet werden (spezielle Methoden, mit denen die Initialisierung gesteuert werden kann).

Wenn sich ein Objekt nicht mehr im Gültigkeitsbereich befindet, wird es von der Common Language Runtime (CLR) freigegeben. Visual Basic steuert die Freigabe von Systemressourcen mit Prozeduren, die als Destruktoren bezeichnet werden. Konstruktoren und Destruktoren unterstützen gemeinsam die Erstellung stabiler und vorhersehbarer Klassenbibliotheken.

"Sub New" und "Sub Finalize"

Die Sub New-Prozedur und die Sub Finalize-Prozedur in Visual Basic initialisieren bzw. zerstören Objekte. Sie ersetzen die in Visual Basic 6.0 und früheren Versionen verwendete Class_Initialize-Methode und Class_Terminate-Methode. Im Gegensatz zu Class_Initialize kann der Sub New-Konstruktor nur einmal ausgeführt werden, wenn eine Klasse erstellt wird. Er kann nur von der ersten Codezeile eines anderen Konstruktors derselben oder einer abgeleiteten Klasse aus explizit aufgerufen werden und von nirgendwo sonst. Weiterhin wird der Code in der Sub New-Methode immer vor jedem anderen Code in einer Klasse ausgeführt. Visual Basic 2005 und höhere Versionen erstellen zur Laufzeit implizit einen Sub New-Konstruktor, wenn Sie nicht explizit eine Sub New-Prozedur für eine Klasse definieren.

Vor der Freigabe von Objekten ruft die CLR automatisch die Finalize-Methode für Objekte auf, die eine Sub Finalize-Prozedur definieren. Die Finalize-Methode kann Code enthalten, der direkt vor der Zerstörung eines Objekts ausgeführt werden muss, z. B. Code zum Schließen von Dateien und Speichern von Zustandsinformationen. Durch Ausführung von Sub Finalize kommt es zu leichten Leistungseinbußen. Sie sollten deshalb nur dann eine Sub Finalize-Methode definieren, wenn Objekte explizit freigegeben werden müssen.

Hinweis:

Der Garbage Collector in der CLR gibt nicht verwaltete Objekte nicht frei (und kann sie nicht freigeben). Dies sind Objekte, die vom Betriebssystem direkt, außerhalb der CLR-Umgebung, ausgeführt werden. Der Grund hierfür ist, dass unterschiedliche nicht verwaltete Objekte auf verschiedene Weise freigegeben werden müssen. Diese Informationen sind den nicht verwalteten Objekten nicht direkt zugeordnet. Sie müssen in der Dokumentation des betreffenden Objekts gesucht werden. Eine Klasse, die nicht verwaltete Objekte verwendet, muss sie in ihrer Finalize-Methode freigeben.

Der Finalize-Destruktor ist eine geschützte Methode, die nur über die zugehörige Klasse oder über abgeleitete Klassen aufgerufen werden kann. Das System ruft Finalize automatisch auf, wenn ein Objekt zerstört wird. Sie sollten deshalb Finalize nicht explizit von außerhalb der Finalize-Implementierung einer abgeleiteten Klasse aufrufen.

Im Unterschied zur Class_Terminate-Methode, die ausgeführt wird, sobald ein Objekt auf Nothing festgelegt wurde, erfolgt der Aufruf des Finalize-Destruktors durch Visual Basic nicht sofort, wenn ein Objekt seinen Gültigkeitsbereich verliert. Visual Basic 2005 und höhere Versionen lassen eine zweite Art von Destruktor zu, Dispose. Diese Methode kann jederzeit explizit aufgerufen werden, um Ressourcen sofort freizugeben.

Hinweis:

Ein Finalize-Destruktor sollte keine Ausnahmen auslösen, da die Anwendung sie nicht behandeln kann und sie das Beenden der Anwendung verursachen können.

IDisposable-Schnittstelle

Klasseninstanzen steuern oft nicht von der CLR verwaltete Ressourcen, z. B. Windows-Handles und Datenbankverbindungen. Diese Ressourcen müssen in der Finalize-Methode der Klasse freigegeben werden, sodass sie freigegeben werden, wenn das Objekt vom Garbage Collector zerstört wird. Der Garbage Collector zerstört Objekte jedoch nur, wenn die CLR mehr freien Arbeitsspeicher erfordert. Daher werden die Ressourcen möglicherweise erst zerstört, nachdem sich das Objekt schon lange nicht mehr im Gültigkeitsbereich befindet.

Zur Ergänzung der Garbage Collection können die Klassen durch Implementierung der IDisposable-Schnittstelle einen Mechanismus für die aktive Verwaltung von Systemressourcen bereitstellen. IDisposable verfügt über die Methode Dispose, die von Clients aufgerufen sollte, wenn sie ein Objekt nicht länger verwenden. Sie können die Dispose-Methode verwenden, um Ressourcen sofort freizugeben und Aufgaben, z. B. das Schließen von Dateien und das Beenden von Datenbankverbindungen, auszuführen. Im Unterschied zum Finalize-Destruktor wird die Dispose-Methode nicht automatisch aufgerufen. Clients einer Klasse müssen Dispose explizit aufrufen, wenn Ressourcen sofort freigegeben werden sollen.

Implementieren von IDisposable

Eine Klasse, die die IDisposable-Schnittstelle implementiert, sollte diese Codeabschnitte enthalten:

  • Ein Feld, um nachzuverfolgen, ob das Objekt freigegeben wurde:

    Protected disposed As Boolean = False
    
  • Eine Überladung von Dispose, die die Ressourcen der Klasse freigibt. Diese Methode sollte von der Dispose-Methode und der Finalize-Methode der Basisklasse aufgerufen werden:

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposed Then
            If disposing Then
                ' Insert code to free managed resources.
            End If
            ' Insert code to free unmanaged resources.
        End If
        Me.disposed = True
    End Sub
    
  • Eine Implementierung von Dispose, die nur folgenden Code enthält:

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
  • Eine Überschreibung der Finalize-Methode, die nur folgenden Code enthält:

    Protected Overrides Sub Finalize()
        Dispose(False)
        MyBase.Finalize()
    End Sub
    

Ableiten von einer Klasse, die IDisposable implementiert

Eine Klasse, die von einer Basisklasse abgeleitet wird, die die IDisposable-Schnittstelle implementiert, muss keine Basismethoden überschreiben, es sei denn, sie verwendet zusätzliche Ressourcen, die freigegeben werden müssen. In diesem Fall muss die abgeleitete Klasse die Dispose(disposing)-Methode der Basisklasse überschreiben, um die Ressourcen der abgeleiteten Klasse freizugeben. Diese Überschreibung muss die Dispose(disposing)-Methode der Basisklasse aufrufen.

Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    If Not Me.disposed Then
        If disposing Then
            ' Insert code to free managed resources.
        End If
        ' Insert code to free unmanaged resources.
    End If
    MyBase.Dispose(disposing)
End Sub

Eine abgeleitete Klasse darf die Dispose-Methode und die Finalize-Methode der Basisklasse nicht überschreiben. Wenn diese Methoden aus einer Instanz der abgeleiteten Klasse aufgerufen werden, ruft die Basisklassenimplementierung dieser Methoden die Überschreibung der Dispose(disposing)-Methode der abgeleiteten Klasse auf.

Visualisierung

Im folgenden Diagramm wird dargestellt, welche Methoden geerbt und welche Methoden in der abgeleiteten Klasse überschrieben werden.

Wenn dieses Dispose-Finalize-Muster befolgt wird, werden die Ressourcen der abgeleiteten Klasse und der Basisklasse ordnungsgemäß freigegeben. Im folgenden Diagramm wird dargestellt, welche Methoden aufgerufen werden, wenn die Klassen freigegeben und beendet werden.

Garbage Collection und Finalize-Destruktor

.NET Framework verwendet das System der verweisverfolgenden Garbage Collection, um nicht verwendete Ressourcen in regelmäßigen Abständen freizugeben. In Visual Basic 6.0 und früheren Versionen wurde ein anderes System mit der Bezeichnung Verweiszählung zum Verwalten von Ressourcen verwendet. Obwohl beide Systeme dieselbe Funktion automatisch ausführen, gibt es doch einige bedeutende Unterschiede.

Die CLR zerstört Objekte in regelmäßigen Abständen, wenn das System feststellt, dass diese Objekte nicht mehr benötigt werden. Wenn es in einem System zu einem Ressourcenengpass kommt, werden Objekte schneller freigegeben, wenn reichlich Ressourcen vorhanden sind, werden Objekte dagegen weniger schnell freigegeben. Die Verzögerung zwischen dem Verlust des Gültigkeitsbereichs eines Objekts und der Freigabe durch die CLR bedeutet, dass Sie im Unterschied zu Visual Basic 6.0 und früheren Versionen nicht genau bestimmen können, wann ein Objekt zerstört wird. Daher weisen Objekte eine nicht deterministische Lebensdauer auf. In den meisten Fällen hat eine nicht deterministische Lebensdauer keinen Einfluss auf das Schreiben von Anwendungen, solange beachtet wird, dass der Finalize-Destruktor möglicherweise nicht sofort nach Verlust des Gültigkeitsbereichs eines Objekts ausgeführt wird.

Ein weiterer Unterschied zu Garbage Collection-Systemen betrifft die Verwendung von Nothing. Um vom Vorteil der Verweiszählung in Visual Basic 6.0 und früheren Versionen Gebrauch zu machen, wiesen Programmierer zuweilen Objektvariablen Nothing zu, um die an diese Variablen gebundenen Verweise freizugeben. Wenn die Variable den letzten Verweis auf das Objekt enthielt, wurden die Ressourcen des Objekts sofort freigegeben. Zwar gibt es in höheren Visual Basic-Versionen immer noch Fälle, in denen diese Prozedur sinnvoll ist, doch führt deren Ausführung nie dazu, dass das Objekt, auf das verwiesen wird, seine Ressourcen sofort freigibt. Um Ressourcen sofort freizugeben, verwenden Sie ggf. die Dispose-Methode des Objekts. Sie sollten eine Variable nur dann auf Nothing festlegen, wenn sie im Vergleich zu dem Zeitraum, den der Garbage Collector zum Auffinden verwaister Objekte benötigt, über eine lange Lebensdauer verfügt.

Siehe auch

Aufgaben

Gewusst wie: Implementieren des Dispose-Finalize-Musters (Visual Basic)

Konzepte

Initialisierung und Beendigung von Komponenten

Finalize-Methoden und Destruktoren

Referenz

Verwenden von Konstruktoren und Destruktoren

New (Visual Basic)

Dispose

Nothing (Visual Basic)

Weitere Ressourcen

Änderungen in der Programmiersprache für Visual Basic 6.0-Benutzer