Události
Vytváření inteligentních aplikací
17. 3. 23 - 21. 3. 23
Připojte se k řadě meetupů a vytvořte škálovatelná řešení AI založená na skutečných případech použití s kolegy vývojáři a odborníky.
ZaregistrovatTento prohlížeč se už nepodporuje.
Upgradujte na Microsoft Edge, abyste mohli využívat nejnovější funkce, aktualizace zabezpečení a technickou podporu.
Finalizátory (historicky označované jako destruktory) slouží k provedení jakéhokoli nezbytného konečného vyčištění při shromažďování instance třídy uvolňováním paměti. Ve většině případů se můžete vyhnout zápisu finalizátoru pomocí System.Runtime.InteropServices.SafeHandle nebo odvozených tříd zabalit všechny nespravované popisovače.
Následuje například deklarace finalizátoru Car
pro třídu.
class Car
{
~Car() // finalizer
{
// cleanup statements...
}
}
Finalizátor lze také implementovat jako definici těla výrazu, jak ukazuje následující příklad.
public class Destroyer
{
public override string ToString() => GetType().Name;
~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");
}
Finalizátor implicitně volá Finalize základní třídu objektu. Proto je volání finalizátoru implicitně přeloženo do následujícího kódu:
protected override void Finalize()
{
try
{
// Cleanup statements...
}
finally
{
base.Finalize();
}
}
Tento návrh znamená, že Finalize
metoda je volána rekurzivně pro všechny instance v řetězci dědičnosti, od nejvíce odvozené po nejméně odvozené.
Poznámka
Prázdné finalizační metody by neměly být použity. Pokud třída obsahuje finalizátor, položka je vytvořena ve frontě Finalize
. Tato fronta je zpracována uvolňováním paměti. Když GC zpracuje frontu, volá každou finalizační metodu. Zbytečné finalizační metody, včetně prázdných finalizátorů, finalizátorů, které volají pouze finalizátor základní třídy, nebo finalizátory, které volají pouze podmíněně generované metody, způsobují zbytečné ztráty výkonu.
Programátor nemá žádnou kontrolu nad tím, kdy je volána finalizátor; systém uvolňování paměti se rozhodne, kdy se má volat. Systém uvolňování paměti kontroluje objekty, které už aplikace nepoužívá. Pokud se domnívá, že objekt má nárok na dokončení, zavolá finalizátor (pokud existuje) a uvolní paměť použitou k uložení objektu. Je možné vynutit uvolňování paměti voláním Collect, ale ve většině případů by se toto volání mělo vyhnout, protože může způsobit problémy s výkonem.
Poznámka
Zda jsou finalizátory spuštěny jako součást ukončení aplikace, je specifické pro každou implementaci rozhraní .NET. Když se aplikace ukončí, rozhraní .NET Framework se snaží volat finalizační metody pro objekty, které ještě nebyly uvolněny z paměti, pokud takové vyčištění nebylo potlačeno (například voláním metody GC.SuppressFinalize
knihovny). .NET 5 (včetně .NET Core) a novějších verzí nevolají finalizátory jako součást ukončení aplikace. Další informace najdete v tématu o problému GitHubu dotnet/csharpstandard #291.
Pokud potřebujete při ukončení aplikace spolehlivě vyčistit, zaregistrujte obslužnou rutinu System.AppDomain.ProcessExit události. Tato obslužná rutina zajistí IDisposable.Dispose() , IAsyncDisposable.DisposeAsync()že byla volána pro všechny objekty, které vyžadují vyčištění před ukončením aplikace. Protože nemůžete volat Finalize přímo a nemůžete zaručit, že systém uvolňování paměti volá všechny finalizační metody před ukončením, musíte použít Dispose
nebo DisposeAsync
zajistit uvolnění prostředků.
Obecně platí, že jazyk C# nevyžaduje tolik správy paměti pro část vývojáře jako jazyky, které necílily modul runtime s uvolňováním paměti. Důvodem je to, že uvolňování paměti .NET implicitně spravuje přidělení a uvolnění paměti pro vaše objekty. Pokud však vaše aplikace zapouzdřuje nespravované prostředky, jako jsou okna, soubory a síťová připojení, měli byste tyto prostředky uvolnit pomocí finalizačních metod. Pokud je objekt způsobilý k dokončení, systém uvolňování paměti spustí Finalize
metodu objektu.
Pokud vaše aplikace používá nákladný externí prostředek, doporučujeme také poskytnout způsob, jak prostředek explicitně uvolnit předtím, než uvolňování paměti objekt uvolní. Chcete-li uvolnit prostředek, implementujte metodu Dispose
IDisposable z rozhraní, které provádí nezbytné vyčištění objektu. To může výrazně zlepšit výkon aplikace. I když je tato explicitní kontrola nad prostředky, finalizátor se stane zárukou pro vyčištění prostředků, pokud volání Dispose
metody selže.
Další informace o čištění prostředků najdete v následujících článcích:
using
výrokNásledující příklad vytvoří tři třídy, které tvoří řetězec dědičnosti. Třída First
je základní třída, Second
je odvozena z First
a Third
je odvozena z Second
. Všechny tři mají finalizátory. V Main
instanci nejvíce odvozené třídy je vytvořena. Výstup z tohoto kódu závisí na tom, jakou implementaci rozhraní .NET cílí aplikace:
class First
{
~First()
{
System.Diagnostics.Trace.WriteLine("First's finalizer is called.");
}
}
class Second : First
{
~Second()
{
System.Diagnostics.Trace.WriteLine("Second's finalizer is called.");
}
}
class Third : Second
{
~Third()
{
System.Diagnostics.Trace.WriteLine("Third's finalizer is called.");
}
}
/*
Test with code like the following:
Third t = new Third();
t = null;
When objects are finalized, the output would be:
Third's finalizer is called.
Second's finalizer is called.
First's finalizer is called.
*/
Další informace naleznete v části Finalizers specifikace jazyka C#.
Zpětná vazba k produktu .NET
.NET je open source projekt. Vyberte odkaz pro poskytnutí zpětné vazby:
Události
Vytváření inteligentních aplikací
17. 3. 23 - 21. 3. 23
Připojte se k řadě meetupů a vytvořte škálovatelná řešení AI založená na skutečných případech použití s kolegy vývojáři a odborníky.
ZaregistrovatŠkolení
Modul
Správa implementací tříd - Training
Naučte se implementovat třídy pomocí pokročilých technik, jako jsou statické třídy, částečné třídy a inicializátory objektů, které můžou zlepšit čitelnost, udržovatelnost a uspořádání kódu.