Finalizzatori (Guida per programmatori C#)Finalizers (C# Programming Guide)

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.Finalizers (which are also called destructors) are used to perform any necessary final clean-up when a class instance is being collected by the garbage collector.

OsservazioniRemarks

  • I finalizzatori non possono essere definiti negli struct.Finalizers cannot be defined in structs. Vengono usati solo con le classi.They are only used with classes.

  • Una classe può avere un solo finalizzatore.A class can only have one finalizer.

  • I finalizzatori non possono essere ereditati e non è possibile eseguirne l'overload.Finalizers cannot be inherited or overloaded.

  • I finalizzatori non possono essere chiamati.Finalizers cannot be called. Vengono richiamati automaticamente.They are invoked automatically.

  • Un finalizzatore non accetta modificatori e non ha parametri.A finalizer does not take modifiers or have parameters.

Ad esempio, di seguito è riportata la dichiarazione di un finalizzatore per la classe Car.For example, the following is a declaration of a finalizer for the Car class.

class Car
{
    ~Car()  // finalizer
    {
        // cleanup statements...
    }
}

Un finalizzatore può anche essere implementato come definizione di corpo dell'espressione, come illustrato nell'esempio seguente.A finalizer can also be implemented as an expression body definition, as the following example shows.

using System;

public class Destroyer
{
   public override string ToString() => GetType().Name;
   
   ~Destroyer() => Console.WriteLine($"The {ToString()} destructor is executing.");
}

Il finalizzatore chiama implicitamente Finalize per la classe di base dell'oggetto.The finalizer implicitly calls Finalize on the base class of the object. Di conseguenza, una chiamata a un finalizzatore viene convertita implicitamente nel codice seguente:Therefore, a call to a finalizer is implicitly translated to the following code:

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.This means that the Finalize method is called recursively for all instances in the inheritance chain, from the most-derived to the least-derived.

Nota

I finalizzatori vuoti non devono essere usati.Empty finalizers should not be used. Quando una classe contiene un finalizzatore, viene creata una voce nella coda Finalize.When a class contains a finalizer, an entry is created in the Finalize queue. Quando si chiama il finalizzatore, viene richiamato Garbage Collector per elaborare la coda.When the finalizer is called, the garbage collector is invoked to process the queue. Se il finalizzatore è vuoto, si verifica semplicemente un calo di prestazioni.An empty finalizer just causes a needless loss of performance.

Il programmatore non ha alcun controllo sul momento in cui viene chiamato il finalizzatore, poiché il momento è determinato dal Garbage Collector.The programmer has no control over when the finalizer is called because this is determined by the garbage collector. Il Garbage Collector controlla gli oggetti che non vengono più usati dall'applicazione e,The garbage collector checks for objects that are no longer being used by the application. se considera un oggetto idoneo per la finalizzazione, chiama il finalizzatore (se presente) e recupera la memoria usata per archiviare l'oggetto.If it considers an object eligible for finalization, it calls the finalizer (if any) and reclaims the memory used to store the object.

Nelle applicazioni .NET Framework (ma non nelle applicazioni .NET Core) i finalizzatori vengono chiamati anche alla chiusura del programma.In .NET Framework applications (but not in .NET Core applications), finalizers are also called when the program exits.

Sebbene sia possibile forzare l'esecuzione di Garbage Collection chiamando Collect, nella maggior parte dei casi è preferibile non effettuare questa operazione per evitare problemi di prestazioni.It is possible to force garbage collection by calling Collect, but most of the time, this should be avoided because it may create performance issues.

Uso di finalizzatori per liberare risorseUsing finalizers to release resources

In generale C# non richiede una gestione della memoria come quella necessaria quando si sviluppa con un linguaggio che non ha come destinazione un runtime con Garbage Collection.In general, C# does not require as much memory management as is needed when you develop with a language that does not target a runtime with garbage collection. Il Garbage Collector di .NET Framework, infatti, gestisce in modo implicito l'allocazione e il rilascio di memoria per gli oggetti.This is because the .NET Framework garbage collector implicitly manages the allocation and release of memory for your objects. Tuttavia, quando l'applicazione incapsula risorse non gestite come finestre, file e connessioni di rete, è necessario usare i finalizzatori per rendere disponibili tali risorse.However, when your application encapsulates unmanaged resources such as windows, files, and network connections, you should use finalizers to free those resources. Quando l'oggetto è idoneo per la finalizzazione, il Garbage Collector esegue il metodo Finalize dell'oggetto.When the object is eligible for finalization, the garbage collector runs the Finalize method of the object.

Rilascio esplicito di risorseExplicit release of resources

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.If your application is using an expensive external resource, we also recommend that you provide a way to explicitly release the resource before the garbage collector frees the object. A questo scopo, è possibile implementare un metodo Dispose dall'interfaccia IDisposable che esegua la pulitura necessaria per l'oggetto.You do this by implementing a Dispose method from the IDisposable interface that performs the necessary cleanup for the object. Questo consente di migliorare notevolmente le prestazioni dell'applicazione.This can considerably improve the performance of the application. 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.Even with this explicit control over resources, the finalizer becomes a safeguard to clean up resources if the call to the Dispose method failed.

Per informazioni dettagliate sulla pulitura delle risorse, vedere gli argomenti seguenti:For more details about cleaning up resources, see the following topics:

EsempioExample

L'esempio seguente crea tre classi che costituiscono una catena di ereditarietà.The following example creates three classes that make a chain of inheritance. La classe First è la classe base, Second è derivata da First e Third è derivata da Second.The class First is the base class, Second is derived from First, and Third is derived from Second. Tutte e tre hanno finalizzatori.All three have finalizers. In Main viene creata un'istanza della classe più derivata.In Main, an instance of the most-derived class is created. Durante l'esecuzione del programma, si noti che i finalizzatori delle tre classi vengono chiamati automaticamente e in ordine, dalla classe più derivata alla meno derivata.When the program runs, notice that the finalizers for the three classes are called automatically, and in order, from the most-derived to the least-derived.

class First
{
    ~First()
    {
        System.Diagnostics.Trace.WriteLine("First's destructor is called.");
    }
}

class Second : First
{
    ~Second()
    {
        System.Diagnostics.Trace.WriteLine("Second's destructor is called.");
    }
}

class Third : Second
{
    ~Third()
    {
        System.Diagnostics.Trace.WriteLine("Third's destructor is called.");
    }
}

class TestDestructors
{
    static void Main()
    {
        Third t = new Third();
    }

}
/* Output (to VS Output Window):
    Third's destructor is called.
    Second's destructor is called.
    First's destructor is called.
*/

Specifiche del linguaggio C#C# language specification

Per altre informazioni, vedere la sezione Distruttori della specifica del linguaggio C#.For more information, see the Destructors section of the C# language specification.

Vedere ancheSee also