Sdílet prostřednictvím


Doba života objektu: Vytváření a zničení objektů (Visual Basic)

Instance třídy, objektu, je vytvořena pomocí klíčového New slova. Úlohy inicializace se často musí provádět u nových objektů, než se použijí. Mezi běžné úlohy inicializace patří otevírání souborů, připojování k databázím a čtení hodnot klíčů registru. Visual Basic řídí inicializaci nových objektů pomocí procedur nazývaných konstruktory (speciální metody, které umožňují kontrolu nad inicializací).

Jakmile objekt opustí obor, uvolní ho modul CLR (Common Language Runtime). Visual Basic řídí vydání systémových prostředků pomocí procedur nazývaných destruktory. Konstruktory a destruktory společně podporují vytváření robustních a předvídatelných knihoven tříd.

Použití konstruktorů a destruktorů

Konstruktory a destruktory řídí vytváření a zničení objektů. A Sub New postupy v jazyce Visual Basic inicializují a zničí objekty; nahrazují Class_Initialize a Class_Terminate metody používané v jazyce Visual Basic 6.0 a dřívějších verzíchSub Finalize.

Sub New

Konstruktor Sub New lze spustit pouze jednou při vytvoření třídy. Nelze ji volat explicitně jinam než v prvním řádku kódu jiného konstruktoru ze stejné třídy nebo z odvozené třídy. Kromě toho kód v Sub New metodě vždy běží před jakýmkoli jiným kódem ve třídě. Visual Basic implicitně vytvoří Sub New konstruktor za běhu, pokud explicitně nedefinujete proceduru Sub New pro třídu.

Chcete-li vytvořit konstruktor pro třídu, vytvořte proceduru pojmenovanou Sub New kdekoli v definici třídy. Pokud chcete vytvořit parametrizovaný konstruktor, zadejte názvy a datové typy argumentů Sub New stejně, jako byste zadali argumenty pro jakýkoli jiný postup, jako v následujícím kódu:

Sub New(ByVal s As String)

Konstruktory jsou často přetížené, stejně jako v následujícím kódu:

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

Když definujete třídu odvozenou z jiné třídy, první řádek konstruktoru musí být volání konstruktoru základní třídy, pokud základní třída nemá přístupný konstruktor, který nepřijímá žádné parametry. Volání základní třídy, která obsahuje výše uvedený konstruktor, například by byla MyBase.New(s). MyBase.New Jinak je volitelný a modul runtime jazyka Visual Basic ho implicitně volá.

Po napsání kódu pro volání konstruktoru nadřazeného objektu můžete do Sub New procedury přidat jakýkoli další inicializační kód. Sub New může přijímat argumenty při zavolání jako parametrizovaný konstruktor. Tyto parametry jsou předány z procedury volání konstruktoru, Dim AnObject As New ThisClass(X)například .

Dílčí dokončení

Před uvolněním objektů CLR automaticky volá metodu Finalize pro objekty, které definují proceduru Sub Finalize . Metoda Finalize může obsahovat kód, který se musí provést těsně před zničením objektu, například kód pro zavření souborů a uložení informací o stavu. Existuje mírné snížení výkonu při provádění Sub Finalize, takže byste měli definovat metodu Sub Finalize pouze v případě, že potřebujete uvolnit objekty explicitně.

Poznámka:

Uvolňování paměti v MODULU CLR (a nemůže) likvidovat nespravované objekty, objekty, které operační systém spouští přímo mimo prostředí CLR. Důvodem je to, že různé nespravované objekty musí být uvolněny různými způsoby. Tato informace není přímo přidružena k nespravovanému objektu; musí být nalezen v dokumentaci pro objekt. Třída, která používá nespravované objekty, musí z nich v rámci své Finalize metody odstranit.

Destruktor Finalize je chráněná metoda, kterou lze volat pouze z třídy, do které patří, nebo z odvozených tříd. Systém volá Finalize automaticky při zničení objektu, takže byste neměli explicitně volat Finalize mimo implementaci Finalize odvozené třídy.

Na rozdíl od Class_Terminate, který se spustí, jakmile je objekt nastaven na nic, je obvykle zpoždění mezi tím, kdy objekt ztratí obor a když Visual Basic volá Finalize destruktor. Visual Basic .NET umožňuje druhý druh destruktoru, IDisposable.Disposekterý lze explicitně volat kdykoli k okamžitému uvolnění prostředků.

Poznámka:

Finalize Destruktor by neměl vyvolat výjimky, protože aplikace je nemůže zpracovat a může způsobit ukončení aplikace.

Jak fungují nové a finalizované metody v hierarchii tříd

Při každém vytvoření instance třídy se modul CLR (Common Language Runtime) pokusí spustit proceduru s názvem New, pokud v tomto objektu existuje. New je typ procedury, která se nazývá constructor , která se používá k inicializaci nových objektů před spuštěním jakéhokoli jiného kódu v objektu. Konstruktor New lze použít k otevření souborů, připojení k databázím, inicializaci proměnných a o všechny další úlohy, které je potřeba provést před použití objektu.

Při vytvoření instance odvozené třídy se Sub New konstruktor základní třídy spustí nejprve, následovaný konstruktory v odvozených třídách. K tomu dochází, protože první řádek kódu v konstruktoru Sub New používá syntaxi MyBase.New()k volání konstruktoru třídy bezprostředně nad sebou v hierarchii tříd. Konstruktor Sub New se pak volá pro každou třídu v hierarchii tříd, dokud se nedosáhne konstruktoru základní třídy. V tomto okamžiku se kód v konstruktoru pro základní třídu spustí, následovaný kódem v každém konstruktoru ve všech odvozených třídách a kód ve většině odvozených tříd se spustí jako poslední.

Screenshot showing class hierarchy constructors and inheritance.

Pokud objekt již není potřeba, CLR volá metodu Finalize pro tento objekt před uvolněním paměti. Metoda Finalize se nazývá, destructor protože provádí úlohy čištění, jako je ukládání informací o stavu, zavření souborů a připojení k databázím a další úlohy, které je třeba provést před uvolněním objektu.

Screenshot showing the Finalize method destructor.

IDisposable – rozhraní

Instance tříd často řídí prostředky, které nespravuje CLR, jako jsou obslužné rutiny Windows a připojení k databázi. Tyto prostředky musí být uvolněny v Finalize metodě třídy, aby byly uvolněny při zničení objektu uvolňováním paměti. Uvolňování paměti však zničí objekty pouze v případě, že CLR vyžaduje více volné paměti. To znamená, že prostředky nemusí být uvolněny, dokud dlouho poté, co objekt přestane být mimo rozsah.

K doplnění uvolňování paměti mohou třídy poskytnout mechanismus pro aktivní správu systémových prostředků, pokud implementují IDisposable rozhraní. IDisposable má jednu metodu, Disposekterou by klienti měli volat, když dokončí použití objektu. Tuto metodu Dispose můžete použít k okamžitému uvolnění prostředků a provádění úloh, jako jsou zavření souborů a připojení k databázi. Finalize Na rozdíl od destruktoru Dispose není metoda volána automaticky. Klienti třídy musí explicitně volat Dispose , pokud chcete okamžitě uvolnit prostředky.

Implementace IDisposable

Třída, která implementuje IDisposable rozhraní, by měla obsahovat tyto části kódu:

  • Pole pro sledování toho, jestli byl objekt odstraněn:

    Protected disposed As Boolean = False
    
  • Přetížení Dispose , které uvolní prostředky třídy. Tato metoda by měla být volána metodami DisposeFinalize základní třídy:

    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
    
  • Implementace Dispose , která obsahuje pouze následující kód:

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
  • Přepsání Finalize metody, která obsahuje pouze následující kód:

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

Odvození z třídy, která implementuje IDisposable

Třída odvozená od základní třídy, která implementuje IDisposable rozhraní, nemusí přepsat žádnou ze základních metod, pokud nepoužívá další prostředky, které je potřeba odstranit. V takovém případě by odvozená třída měla přepsat metodu základní třídy Dispose(disposing) k odstranění prostředků odvozené třídy. Toto přepsání musí volat metodu Dispose(disposing) základní třídy.

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

Odvozená třída by neměla přepsat základní třídy Dispose a Finalize metody. Pokud jsou tyto metody volána z instance odvozené třídy, implementace základních tříd těchto metod volá přepsání Dispose(disposing) odvozené třídy metody.

Uvolňování paměti a destruktor finalizace

Rozhraní .NET Framework používá systém uvolňování paměti pro trasování odkazů k pravidelnému vydávání nepoužívaných prostředků. Visual Basic 6.0 a starší verze používaly jiný systém označovaný jako počítání odkazů ke správě prostředků. I když oba systémy provádějí stejnou funkci automaticky, existuje několik důležitých rozdílů.

CLR pravidelně zničí objekty, když systém určí, že tyto objekty už nejsou potřeba. Objekty se vydávají rychleji, když jsou systémové prostředky v krátkém zdroji, a méně často v opačném případě. Zpoždění mezi tím, kdy objekt ztratí obor a kdy CLR uvolní, znamená to, že na rozdíl od objektů v jazyce Visual Basic 6.0 a starších verzí nelze přesně určit, kdy bude objekt zničen. V takové situaci se říká, že objekty mají ne deterministické životnosti. Ve většině případů nedeterministické životnosti nemění způsob psaní aplikací, pokud si pamatujete, že Finalize destruktor nemusí být okamžitě spuštěn při ztrátě oboru objektu.

Dalším rozdílem mezi systémy uvolňování paměti je použití Nothing. Pokud chcete využít počítání odkazů v jazyce Visual Basic 6.0 a starších verzích, programátoři někdy přiřazují Nothing proměnné objektů, aby uvolnili odkazy na tyto proměnné. Pokud proměnná držela poslední odkaz na objekt, prostředky objektu byly uvolněny okamžitě. V novějších verzích jazyka Visual Basic mohou existovat případy, kdy je tento postup stále cenný a jeho provedení nikdy nezpůsobí okamžité uvolnění svých prostředků odkazovaným objektem. Pokud chcete uvolnit prostředky okamžitě, použijte metodu objektu Dispose , pokud je k dispozici. Jedinou dobou, na kterou byste měli nastavit proměnnou Nothing , je doba její životnosti vzhledem k době, po kterou uvolňování paměti trvá detekce osamocených objektů.

Viz také