Eventi
Creare app e agenti di intelligenza artificiale
17 mar, 21 - 21 mar, 10
Partecipa alla serie meetup per creare soluzioni di intelligenza artificiale scalabili basate su casi d'uso reali con altri sviluppatori ed esperti.
Iscriviti subitoQuesto browser non è più supportato.
Esegui l'aggiornamento a Microsoft Edge per sfruttare i vantaggi di funzionalità più recenti, aggiornamenti della sicurezza e supporto tecnico.
I finalizzatori (detti anche distruttori) vengono usati per eseguire operazioni di pulizia finale eventualmente necessarie quando un'istanza di classe viene raccolta da Garbage Collector. Nella maggior parte dei casi, è possibile evitare di scrivere un finalizzatore usando System.Runtime.InteropServices.SafeHandle o le classi derivate o per eseguire il wrapping di qualsiasi handle non gestito.
Ad esempio, di seguito è riportata la dichiarazione di un finalizzatore per la classe Car
.
class Car
{
~Car() // finalizer
{
// cleanup statements...
}
}
Un finalizzatore può anche essere implementato come definizione di corpo dell'espressione, come illustrato nell'esempio seguente.
public class Destroyer
{
public override string ToString() => GetType().Name;
~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");
}
Il finalizzatore chiama implicitamente Finalize per la classe di base dell'oggetto. Di conseguenza, una chiamata a un finalizzatore viene convertita implicitamente nel codice seguente:
protected override void Finalize()
{
try
{
// Cleanup statements...
}
finally
{
base.Finalize();
}
}
In questo modo, il metodo Finalize
viene chiamato in modo ricorsivo per tutte le istanze nella catena di ereditarietà, dalla più derivata alla meno derivata.
Nota
I finalizzatori vuoti non devono essere usati. Quando una classe contiene un finalizzatore, viene creata una voce nella coda Finalize
. Questa coda viene elaborata dal Garbage Collector. Quando GC elabora la coda, chiama ogni finalizzatore. I finalizzatori non necessari, inclusi finalizzatori vuoti, finalizzatori che chiamano solo il finalizzatore della classe base o finalizzatori che chiamano solo metodi generati in modo condizionale, causano una perdita di prestazioni inutile.
Il programmatore non ha alcun controllo sul momento in cui viene chiamato il finalizzatore, è il Garbage Collector a decidere quando chiamarlo. Il Garbage Collector controlla gli oggetti che non vengono più usati dall'applicazione e, se considera un oggetto idoneo per la finalizzazione, chiama il finalizzatore (se presente) e recupera la memoria usata per archiviare l'oggetto. Sebbene sia possibile forzare l'esecuzione di Garbage Collection chiamando Collect, nella maggior parte dei casi è preferibile non effettuare questa chiamata per evitare problemi di prestazioni.
Nota
Se i finalizzatori vengono eseguiti come parte della terminazione dell'applicazione dipende da ogni implementazione di .NET. Quando un'applicazione termina, .NET Framework esegue ogni ragionevole sforzo per chiamare finalizzatori per gli oggetti che non sono ancora stati sottoposti a Garbage Collection, a meno che tale pulizia non sia stata eliminata (ad esempio da una chiamata al metodo di libreria GC.SuppressFinalize
). .NET 5 (incluso .NET Core) e versioni successive non chiamano finalizzatori come parte della terminazione dell'applicazione. Per altre informazioni, vedere il problema di GitHub #291 in dotnet/csharpstandard.
Se è necessario eseguire la pulizia in modo affidabile quando un'applicazione viene chiusa, registrare un gestore per l'evento System.AppDomain.ProcessExit. Tale gestore garantisce che IDisposable.Dispose() (o IAsyncDisposable.DisposeAsync()) sia stato chiamato per tutti gli oggetti che richiedono la pulizia prima dell'uscita dall'applicazione. Poiché non è possibile chiamare Finalize direttamente e non è possibile garantire che il Garbage Collector chiami tutti i finalizzatori prima dell'uscita, è necessario usare Dispose
o DisposeAsync
per assicurarsi che le risorse vengano liberate.
In generale, C# non richiede la gestione della memoria da parte dello sviluppatore, come i linguaggi che non hanno come destinazione un runtime con Garbage Collection. Il Garbage Collector di .NET, infatti, gestisce in modo implicito l'allocazione e il rilascio di memoria per gli oggetti. Tuttavia, quando l'applicazione incapsula risorse non gestite come finestre, file e connessioni di rete, è necessario usare i finalizzatori per rendere disponibili tali risorse. Quando l'oggetto è idoneo per la finalizzazione, il Garbage Collector esegue il metodo Finalize
dell'oggetto.
Se l'applicazione usa una risorsa esterna che consuma molta memoria, è consigliabile specificare un modo per rilasciare la risorsa in modo esplicito prima che il Garbage Collector renda disponibile l'oggetto. Per rilasciare la risorsa, implementare un metodo Dispose
dall'interfaccia IDisposable che esegue la pulizia necessaria per l'oggetto. Questo consente di migliorare notevolmente le prestazioni dell'applicazione. Nonostante questo controllo esplicito sulle risorse, il finalizzatore consente di salvaguardare la pulitura delle risorse nei casi in cui la chiamata al metodo Dispose
non venga eseguita correttamente.
Per altre informazioni sulla pulitura delle risorse, vedere gli articoli seguenti:
using
L'esempio seguente crea tre classi che costituiscono una catena di ereditarietà. La classe First
è la classe base, Second
è derivata da First
e Third
è derivata da Second
. Tutte e tre hanno finalizzatori. In Main
viene creata un'istanza della classe più derivata. L'output di questo codice dipende dall'implementazione di .NET di destinazione dell'applicazione:
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.
*/
Per altre informazioni, vedere la sezione Finalizzatori della specifica del linguaggio C#.
Feedback su .NET
.NET è un progetto di open source. Selezionare un collegamento per fornire feedback:
Eventi
Creare app e agenti di intelligenza artificiale
17 mar, 21 - 21 mar, 10
Partecipa alla serie meetup per creare soluzioni di intelligenza artificiale scalabili basate su casi d'uso reali con altri sviluppatori ed esperti.
Iscriviti subitoFormazione
Modulo
Gestire le implementazioni della classe - Training
Informazioni su come implementare classi usando tecniche avanzate come classi statiche, classi parziali e inizializzatori di oggetti che possono migliorare la leggibilità, la gestibilità e l'organizzazione del codice.