Delen via


Levensduur van objecten: hoe objecten worden gemaakt en vernietigd (Visual Basic)

Een exemplaar van een klasse, een object, wordt gemaakt met behulp van het New trefwoord. Initialisatietaken moeten vaak worden uitgevoerd op nieuwe objecten voordat ze worden gebruikt. Algemene initialisatietaken omvatten het openen van bestanden, het maken van verbinding met databases en het lezen van waarden van registersleutels. Visual Basic bepaalt de initialisatie van nieuwe objecten met behulp van procedures die constructors worden genoemd (speciale methoden die controle over initialisatie mogelijk maken).

Nadat een object het bereik verlaat, wordt het vrijgegeven door de Common Language Runtime (CLR). Visual Basic bepaalt de release van systeembronnen met behulp van procedures die destructors worden genoemd. Samen ondersteunen constructors en destructors het maken van robuuste en voorspelbare klassebibliotheken.

Constructors en destructors gebruiken

Constructors en destructors bepalen het creëren en vernietigen van objecten. De Sub New en Sub Finalize procedures in Visual Basic initialiseren en vernietigen objecten; ze vervangen de Class_Initialize methoden en Class_Terminate methoden die worden gebruikt in Visual Basic 6.0 en eerdere versies.

Sub nieuw

De Sub New constructor kan slechts eenmaal worden uitgevoerd wanneer een klasse wordt gemaakt. Het kan niet expliciet anders worden aangeroepen dan in de eerste regel code van een andere constructor van dezelfde klasse of van een afgeleide klasse. Bovendien wordt de code in de Sub New methode altijd uitgevoerd vóór andere code in een klasse. Visual Basic maakt impliciet een Sub New constructor tijdens runtime als u niet expliciet een Sub New procedure voor een klasse definieert.

Als u een constructor voor een klasse wilt maken, maakt u een procedure met de naam Sub New overal in de klassedefinitie. Als u een geparameteriseerde constructor wilt maken, geeft u de namen en gegevenstypen van argumenten op op Sub New dezelfde manier als voor elke andere procedure, zoals in de volgende code:

Sub New(ByVal s As String)

Constructors worden vaak overbelast, zoals in de volgende code:

Sub New(ByVal s As String, i As Integer)

Wanneer u een klasse definieert die is afgeleid van een andere klasse, moet de eerste regel van een constructor een aanroep naar de constructor van de basisklasse zijn, tenzij de basisklasse een toegankelijke constructor heeft die geen parameters accepteert. Een aanroep naar de basisklasse die de bovenstaande constructor bevat, zou bijvoorbeeld zijn MyBase.New(s). Anders is MyBase.New dit optioneel en roept de Visual Basic-runtime deze impliciet aan.

Nadat u de code hebt geschreven om de constructor van het bovenliggende object aan te roepen, kunt u aanvullende initialisatiecode toevoegen aan de Sub New procedure. Sub New kan argumenten accepteren wanneer deze worden aangeroepen als een geparameteriseerde constructor. Deze parameters worden doorgegeven vanuit de procedure die de constructor aanroept, bijvoorbeeld Dim AnObject As New ThisClass(X).

Subaftotaal voltooien

Voordat u objecten vrijgeeft, roept de CLR automatisch de Finalize methode aan voor objecten die een Sub Finalize procedure definiëren. De Finalize methode kan code bevatten die moet worden uitgevoerd vlak voordat een object wordt vernietigd, zoals code voor het sluiten van bestanden en het opslaan van statusgegevens. Er is een lichte prestatiestraf voor het Sub Finalizeuitvoeren, dus u moet alleen een Sub Finalize methode definiëren wanneer u objecten expliciet moet vrijgeven.

Notitie

De garbagecollector in de CLR verwijdert niet (en kan niet) onbeheerde objecten verwijderen , objecten die het besturingssysteem rechtstreeks uitvoert, buiten de CLR-omgeving. Dit komt doordat verschillende onbeheerde objecten op verschillende manieren moeten worden verwijderd. Deze informatie is niet rechtstreeks gekoppeld aan het onbeheerde object; deze moet worden gevonden in de documentatie voor het object. Een klasse die onbeheerde objecten gebruikt, moet deze in de Finalize bijbehorende methode verwijderen.

De Finalize destructor is een beveiligde methode die alleen kan worden aangeroepen vanuit de klasse waartoe deze behoort, of van afgeleide klassen. Het systeem roept Finalize automatisch aan wanneer een object wordt vernietigd, dus u moet niet expliciet aanroepen Finalize van buiten de implementatie van een afgeleide klasse Finalize .

In tegenstelling tot Class_Terminate, dat wordt uitgevoerd zodra een object op niets is ingesteld, is er meestal een vertraging tussen wanneer een object het bereik verliest en wanneer Visual Basic destructor Finalize aanroept. Visual Basic .NET biedt een tweede soort destructor, IDisposable.Disposedie op elk gewenst moment expliciet kan worden aangeroepen om resources onmiddellijk vrij te geven.

Notitie

Een Finalize destructor mag geen uitzonderingen genereren, omdat deze niet door de toepassing kunnen worden verwerkt en de toepassing kan worden beëindigd.

Hoe nieuwe methoden werken en voltooien in een klassehiërarchie

Wanneer een exemplaar van een klasse wordt gemaakt, probeert de Common Language Runtime (CLR) een procedure met de naam Newuit te voeren, als deze bestaat in dat object. New is een type procedure dat wordt constructor gebruikt om nieuwe objecten te initialiseren voordat andere code in een object wordt uitgevoerd. Een New constructor kan worden gebruikt om bestanden te openen, verbinding te maken met databases, variabelen te initialiseren en andere taken uit te voeren die moeten worden uitgevoerd voordat een object kan worden gebruikt.

Wanneer een exemplaar van een afgeleide klasse wordt gemaakt, wordt de Sub New constructor van de basisklasse eerst uitgevoerd, gevolgd door constructors in afgeleide klassen. Dit gebeurt omdat de eerste regel code in een Sub New constructor de syntaxis MyBase.New()gebruikt om de constructor van de klasse direct boven zichzelf in de klassehiërarchie aan te roepen. De Sub New constructor wordt vervolgens aangeroepen voor elke klasse in de klassehiërarchie totdat de constructor voor de basisklasse is bereikt. Op dat moment wordt de code in de constructor voor de basisklasse uitgevoerd, gevolgd door de code in elke constructor in alle afgeleide klassen en wordt de code in de meest afgeleide klassen als laatste uitgevoerd.

Screenshot showing class hierarchy constructors and inheritance.

Wanneer een object niet meer nodig is, roept de CLR de Finalize methode voor dat object aan voordat het geheugen wordt vrijgemaakt. De Finalize methode wordt een destructor genoemd omdat er opschoontaken worden uitgevoerd, zoals het opslaan van statusgegevens, het sluiten van bestanden en verbindingen met databases en andere taken die moeten worden uitgevoerd voordat het object wordt vrijgegeven.

Screenshot showing the Finalize method destructor.

IDisposable Interface

Klasse-exemplaren beheren vaak resources die niet worden beheerd door de CLR, zoals Windows-ingangen en databaseverbindingen. Deze resources moeten worden verwijderd in de Finalize methode van de klasse, zodat ze worden vrijgegeven wanneer het object wordt vernietigd door de garbagecollection. De garbagecollector vernietigt echter alleen objecten wanneer de CLR meer vrije geheugen nodig heeft. Dit betekent dat de resources mogelijk pas worden vrijgegeven nadat het object buiten het bereik valt.

Als aanvulling op garbagecollection kunnen uw klassen een mechanisme bieden om systeembronnen actief te beheren als ze de IDisposable interface implementeren. IDisposable heeft één methode, Disposedie clients moeten aanroepen wanneer ze klaar zijn met het gebruik van een object. U kunt de Dispose methode gebruiken om resources onmiddellijk vrij te geven en taken uit te voeren, zoals het sluiten van bestanden en databaseverbindingen. In tegenstelling tot de Finalize destructor wordt de Dispose methode niet automatisch aangeroepen. Clients van een klasse moeten expliciet aanroepen Dispose wanneer u onmiddellijk resources wilt vrijgeven.

IDisposable implementeren

Een klasse die de IDisposable interface implementeert, moet de volgende codesecties bevatten:

  • Een veld om bij te houden of het object is verwijderd:

    Protected disposed As Boolean = False
    
  • Een overbelasting van de Dispose resources van de klasse. Deze methode moet worden aangeroepen door de Dispose en Finalize methoden van de basisklasse:

    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
    
  • Een implementatie van Dispose die alleen de volgende code bevat:

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
  • Een onderdrukking van de Finalize methode die alleen de volgende code bevat:

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

Afgeleid van een klasse die IDisposable implementeert

Een klasse die is afgeleid van een basisklasse die de IDisposable interface implementeert, hoeft geen van de basismethoden te overschrijven, tenzij er extra resources worden gebruikt die moeten worden verwijderd. In dat geval moet de afgeleide klasse de methode van Dispose(disposing) de basisklasse overschrijven om de resources van de afgeleide klasse te verwijderen. Deze onderdrukking moet de methode van Dispose(disposing) de basisklasse aanroepen.

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

Een afgeleide klasse mag de basisklasse Dispose en Finalize methoden niet overschrijven. Wanneer deze methoden worden aangeroepen vanuit een exemplaar van de afgeleide klasse, roept de implementatie van de basisklasse van deze methoden de onderdrukking van de methode van de Dispose(disposing) afgeleide klasse aan.

Garbagecollection en de destructor voltooien

Het .NET Framework maakt gebruik van het garbagecollectionsysteem referentietracering om periodiek ongebruikte resources vrij te geven. Visual Basic 6.0 en eerdere versies gebruikten een ander systeem, verwijzing tellen genoemd om resources te beheren. Hoewel beide systemen dezelfde functie automatisch uitvoeren, zijn er enkele belangrijke verschillen.

De CLR vernietigt periodiek objecten wanneer het systeem bepaalt dat dergelijke objecten niet meer nodig zijn. Objecten worden sneller vrijgegeven wanneer systeemresources in korte levering zijn en minder vaak anders. De vertraging tussen wanneer een object het bereik verliest en wanneer de CLR vrijgeeft, betekent dit dat, in tegenstelling tot objecten in Visual Basic 6.0 en eerdere versies, u niet precies kunt bepalen wanneer het object wordt vernietigd. In een dergelijke situatie wordt gezegd dat objecten een niet-deterministische levensduur hebben. In de meeste gevallen verandert de niet-deterministische levensduur niet hoe u toepassingen schrijft, zolang u zich herinnert dat de Finalize destructor mogelijk niet onmiddellijk wordt uitgevoerd wanneer een object het bereik verliest.

Een ander verschil tussen de garbagecollection-systemen omvat het gebruik van Nothing. Om te profiteren van het tellen van verwijzingen in Visual Basic 6.0 en eerdere versies, hebben programmeurs soms toegewezen Nothing aan objectvariabelen om de verwijzingen die variabelen bevatten vrij te geven. Als de variabele de laatste verwijzing naar het object heeft, zijn de resources van het object onmiddellijk vrijgegeven. In latere versies van Visual Basic kunnen er gevallen zijn waarin deze procedure nog steeds waardevol is, waardoor het object waarnaar wordt verwezen nooit onmiddellijk de resources vrijgeeft. Als u resources onmiddellijk wilt vrijgeven, gebruikt u de methode van Dispose het object, indien beschikbaar. De enige tijd waarop u een variabele Nothing moet instellen, is wanneer de levensduur ervan lang is ten opzichte van de tijd die de garbagecollector nodig heeft om zwevende objecten te detecteren.

Zie ook