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í.
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.
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 Dispose
Finalize
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ů.