Objektlivslängd: Hur objekt skapas och förstörs (Visual Basic)

En instans av en klass, ett objekt, skapas med hjälp av nyckelordet New . Initieringsuppgifter måste ofta utföras på nya objekt innan de används. Vanliga initieringsuppgifter är att öppna filer, ansluta till databaser och läsa värden för registernycklar. Visual Basic styr initieringen av nya objekt med hjälp av procedurer som kallas konstruktorer (särskilda metoder som tillåter kontroll över initiering).

När ett objekt lämnar omfånget släpps det av CLR (Common Language Runtime). Visual Basic styr versionen av systemresurser med hjälp av procedurer som kallas destructors. Tillsammans stöder konstruktorer och destruatorer skapandet av robusta och förutsägbara klassbibliotek.

Använda konstruktorer och destruktörer

Konstruktorer och destruktorer styr skapandet och förstörelsen av objekt. Procedurerna Sub New och Sub Finalize i Visual Basic initierar och förstör objekt. De ersätter metoderna Class_Initialize och Class_Terminate som används i Visual Basic 6.0 och tidigare versioner.

Under ny

Konstruktorn Sub New kan bara köras en gång när en klass skapas. Den kan inte anropas explicit någon annanstans än i den första kodraden för en annan konstruktor från antingen samma klass eller från en härledd klass. Dessutom körs koden i Sub New metoden alltid före någon annan kod i en klass. Visual Basic skapar implicit en Sub New konstruktor vid körning om du inte uttryckligen definierar en Sub New procedur för en klass.

Skapa en konstruktor för en klass genom att skapa en procedur med namnet Sub New var som helst i klassdefinitionen. Om du vill skapa en parameteriserad konstruktor anger du namn och datatyper av argument på Sub New samma sätt som du anger argument för andra procedurer, som i följande kod:

Sub New(ByVal s As String)

Konstruktorer överbelastas ofta, som i följande kod:

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

När du definierar en klass som härletts från en annan klass måste den första raden i en konstruktor vara ett anrop till konstruktorn för basklassen, såvida inte basklassen har en tillgänglig konstruktor som inte tar några parametrar. Ett anrop till basklassen som innehåller konstruktorn ovan är MyBase.New(s)till exempel . Annars MyBase.New är det valfritt och Visual Basic-körningen anropar det implicit.

När du har skrivit koden för att anropa det överordnade objektets konstruktor kan du lägga till ytterligare initieringskod i proceduren Sub New . Sub New kan acceptera argument när de anropas som en parameteriserad konstruktor. Dessa parametrar skickas från proceduren som anropar konstruktorn, Dim AnObject As New ThisClass(X)till exempel .

Underslut

Innan objekt frigörs anropar Finalize CLR automatiskt metoden för objekt som definierar en Sub Finalize procedur. Metoden Finalize kan innehålla kod som måste köras precis innan ett objekt förstörs, till exempel kod för att stänga filer och spara tillståndsinformation. Det finns en liten prestandaförseelse för att Sub Finalizeköra , så du bör definiera en Sub Finalize metod endast när du behöver släppa objekt explicit.

Kommentar

Skräpinsamlaren i CLR tar inte bort (och kan inte) ta bort ohanterade objekt, objekt som operativsystemet kör direkt utanför CLR-miljön. Det beror på att olika ohanterade objekt måste tas bort på olika sätt. Den informationen är inte direkt kopplad till det ohanterade objektet. det måste hittas i dokumentationen för objektet. En klass som använder ohanterade objekt måste ta bort dem i sin Finalize metod.

Destructor Finalize är en skyddad metod som endast kan anropas från den klass som den tillhör eller från härledda klasser. Systemet anropar Finalize automatiskt när ett objekt förstörs, så du bör inte uttryckligen anropa Finalize utanför implementeringen av en härledd klass Finalize .

Till skillnad från Class_Terminate, som körs så snart ett objekt har angetts till ingenting, uppstår det vanligtvis en fördröjning mellan när ett objekt förlorar omfånget och när Visual Basic anropar Finalize destrukteraren. Visual Basic .NET möjliggör en andra typ av destructor, IDisposable.Dispose, som uttryckligen kan anropas när som helst för att omedelbart frigöra resurser.

Kommentar

En Finalize destructor bör inte utlösa undantag, eftersom de inte kan hanteras av programmet och kan få programmet att avslutas.

Hur nya och slutför metoder fungerar i en klasshierarki

När en instans av en klass skapas försöker CLR (Common Language Runtime) köra en procedur med namnet New, om den finns i objektet. New är en typ av procedur som kallas en constructor som används för att initiera nya objekt innan någon annan kod i ett objekt körs. En New konstruktor kan användas för att öppna filer, ansluta till databaser, initiera variabler och ta hand om andra uppgifter som behöver utföras innan ett objekt kan användas.

När en instans av en härledd klass skapas Sub New körs konstruktorn för basklassen först, följt av konstruktorer i härledda klasser. Detta beror på att den första kodraden i en Sub New konstruktor använder syntaxen MyBase.New()för att anropa konstruktorn för klassen omedelbart ovanför sig själv i klasshierarkin. Konstruktorn Sub New anropas sedan för varje klass i klasshierarkin tills konstruktorn för basklassen har nåtts. Då körs koden i konstruktorn för basklassen, följt av koden i varje konstruktor i alla härledda klasser och koden i de mest härledda klasserna körs sist.

Screenshot showing class hierarchy constructors and inheritance.

När ett objekt inte längre behövs anropar Finalize CLR -metoden för objektet innan dess minne frigörs. Metoden Finalize kallas för en destructor eftersom den utför rensningsuppgifter, till exempel att spara tillståndsinformation, stänga filer och anslutningar till databaser och andra uppgifter som måste utföras innan objektet släpps.

Screenshot showing the Finalize method destructor.

IDisposable-gränssnitt

Klassinstanser styr ofta resurser som inte hanteras av CLR, till exempel Windows-handtag och databasanslutningar. Dessa resurser måste tas bort i -metoden för Finalize klassen, så att de släpps när objektet förstörs av skräpinsamlaren. Skräpinsamlaren förstör dock bara objekt när CLR kräver mer ledigt minne. Det innebär att resurserna kanske inte släpps förrän långt efter att objektet har gått utanför omfånget.

För att komplettera skräpinsamlingen kan klasserna tillhandahålla en mekanism för att aktivt hantera systemresurser om de implementerar IDisposable gränssnittet. IDisposable har en metod, Dispose, som klienter ska anropa när de är klara med ett objekt. Du kan använda Dispose metoden för att omedelbart frigöra resurser och utföra uppgifter som att stänga filer och databasanslutningar. Till skillnad från destructor Finalize anropas Dispose inte metoden automatiskt. Klienter i en klass måste uttryckligen anropa Dispose när du omedelbart vill frigöra resurser.

Implementera IDisposable

En klass som implementerar IDisposable gränssnittet bör innehålla följande kodavsnitt:

  • Ett fält för att hålla reda på om objektet har tagits bort:

    Protected disposed As Boolean = False
    
  • En överlagring av Dispose som frigör klassens resurser. Den här metoden ska anropas av Dispose metoderna och Finalize för basklassen:

    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
    
  • En implementering av Dispose som endast innehåller följande kod:

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
  • En åsidosättning av metoden Finalize som endast innehåller följande kod:

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

Härled från en klass som implementerar IDisposable

En klass som härleds från en basklass som implementerar IDisposable gränssnittet behöver inte åsidosätta någon av basmetoderna om den inte använder ytterligare resurser som behöver tas bort. I så fall bör den härledda klassen åsidosätta basklassens Dispose(disposing) metod för att ta bort den härledda klassens resurser. Den här åsidosättningen måste anropa basklassens Dispose(disposing) metod.

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

En härledd klass bör inte åsidosätta basklassens Dispose och Finalize metoderna. När dessa metoder anropas från en instans av den härledda klassen anropar basklassens implementering av dessa metoder den härledda klassens åsidosättning av Dispose(disposing) metoden.

Skräpinsamling och slutför destructor

.NET Framework använder skräpinsamlingssystemet för referensspårning för att regelbundet frigöra oanvända resurser. Visual Basic 6.0 och tidigare versioner använde ett annat system som kallas referensräkning för att hantera resurser. Även om båda systemen utför samma funktion automatiskt finns det några viktiga skillnader.

CLR förstör regelbundet objekt när systemet fastställer att sådana objekt inte längre behövs. Objekt frigörs snabbare när systemresurserna är en bristvara, och mindre ofta annars. Fördröjningen mellan när ett objekt förlorar omfånget och när CLR släpps innebär det att du, till skillnad från objekt i Visual Basic 6.0 och tidigare versioner, inte kan avgöra exakt när objektet kommer att förstöras. I en sådan situation sägs objekt ha icke-deterministisk livslängd. I de flesta fall ändrar inte icke-deterministisk livslängd hur du skriver program, så länge du kommer ihåg att Finalize destruktor kanske inte omedelbart körs när ett objekt förlorar omfånget.

En annan skillnad mellan systemen för skräpinsamling är användningen av Nothing. För att dra nytta av referensräkning i Visual Basic 6.0 och tidigare versioner tilldelas Nothing programmerare ibland objektvariabler för att frigöra de referenser som dessa variabler innehåller. Om variabeln innehöll den sista referensen till objektet släpptes objektets resurser omedelbart. I senare versioner av Visual Basic, även om det kan finnas fall där den här proceduren fortfarande är värdefull, får det refererade objektet aldrig att frigöra sina resurser omedelbart. Om du vill frigöra resurser omedelbart använder du objektets -metod, om det är Dispose tillgängligt. Den enda tid du bör ange en variabel till Nothing är när dess livslängd är lång i förhållande till den tid skräpinsamlaren tar för att identifiera överblivna objekt.

Se även