Finalizadores (Guía de programación de C#)Finalizers (C# Programming Guide)

Los finalizadores (también denominados destructores) se usan para realizar cualquier limpieza final necesaria cuando el recolector de elementos no utilizados recopila una instancia de clase.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.

ComentariosRemarks

  • Los finalizadores no se pueden definir en structs.Finalizers cannot be defined in structs. Solo se usan con clases.They are only used with classes.

  • Una clase solo puede tener un finalizador.A class can only have one finalizer.

  • Los finalizadores no se pueden heredar ni sobrecargar.Finalizers cannot be inherited or overloaded.

  • No se puede llamar a los finalizadores.Finalizers cannot be called. Se invocan automáticamente.They are invoked automatically.

  • Un finalizador no permite modificadores ni tiene parámetros.A finalizer does not take modifiers or have parameters.

Por ejemplo, el siguiente código muestra una declaración de un finalizador para la clase Car.For example, the following is a declaration of a finalizer for the Car class.

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

Un finalizador también puede implementarse como una definición de cuerpo de expresión, como se muestra en el ejemplo siguiente.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.");
}

El finalizador llama implícitamente a Finalize en la clase base del objeto.The finalizer implicitly calls Finalize on the base class of the object. Por lo tanto, una llamada a un finalizador se convierte implícitamente al siguiente código:Therefore, a call to a finalizer is implicitly translated to the following code:

protected override void Finalize()  
{  
    try  
    {  
        // Cleanup statements...  
    }  
    finally  
    {  
        base.Finalize();  
    }  
}  

Esto significa que se realizan llamadas al método Finalize de manera recursiva para todas las instancias de la cadena de herencia, desde la más a la menos derivada.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

Los finalizadores vacíos no deben usarse.Empty finalizers should not be used. Cuando una clase contiene un finalizador, se crea una entrada en la cola Finalize.When a class contains a finalizer, an entry is created in the Finalize queue. Cuando se llama al finalizador, se invoca al recolector de elementos no utilizados para procesar la cola.When the finalizer is called, the garbage collector is invoked to process the queue. Un finalizador vacío simplemente produce una pérdida de rendimiento innecesaria.An empty finalizer just causes a needless loss of performance.

El programador no puede controlar cuándo se llama al finalizador, porque esto lo determina el recolector de elementos no utilizados.The programmer has no control over when the finalizer is called because this is determined by the garbage collector. El recolector de elementos no utilizados comprueba si hay objetos que ya no están siendo usados por ninguna aplicación.The garbage collector checks for objects that are no longer being used by the application. Si considera un objeto elegible para su finalización, llama al finalizador (si existe) y reclama la memoria usada para almacenar el objeto.If it considers an object eligible for finalization, it calls the finalizer (if any) and reclaims the memory used to store the object.

En las aplicaciones de .NET Framework (pero no en las de .NET Core), cuando se cierra el programa también se llama a los finalizadores.In .NET Framework applications (but not in .NET Core applications), finalizers are also called when the program exits.

Es posible forzar la recolección de elementos no utilizados llamando a Collect, pero en general debe evitarse su uso por razones de rendimiento.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 de finalizadores para liberar recursosUsing finalizers to release resources

En general, C# no requiere tanta administración de memoria como se necesita al desarrollar con un lenguaje que no está diseñado para un runtime con recolección de elementos no utilizados.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. Esto es debido a que el recolector de elementos no utilizados de .NET Framework administra implícitamente la asignación y liberación de memoria para los objetos.This is because the .NET Framework garbage collector implicitly manages the allocation and release of memory for your objects. En cambio, cuando la aplicación encapsule recursos no administrados como ventanas, archivos y conexiones de red, debería usar finalizadores para liberar dichos recursos.However, when your application encapsulates unmanaged resources such as windows, files, and network connections, you should use finalizers to free those resources. Cuando el objeto cumple los requisitos para su finalización, el recolector de elementos no utilizados ejecuta el método Finalize del objeto.When the object is eligible for finalization, the garbage collector runs the Finalize method of the object.

Liberación explícita de recursosExplicit release of resources

Si la aplicación usa un recurso externo costoso, también es recomendable liberar explícitamente el recurso antes de que el recolector de elementos no utilizados libere el objeto.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. Para ello debe implementar un método Dispose desde la interfaz IDisposable que realiza la limpieza del objeto necesaria.You do this by implementing a Dispose method from the IDisposable interface that performs the necessary cleanup for the object. Esto puede mejorar considerablemente el rendimiento de la aplicación.This can considerably improve the performance of the application. Aunque controle explícitamente los recursos, el finalizador garantiza la liberación de recursos si la llamada al método Dispose genera un error.Even with this explicit control over resources, the finalizer becomes a safeguard to clean up resources if the call to the Dispose method failed.

Para obtener más detalles sobre la liberación de recursos, vea los siguientes temas:For more details about cleaning up resources, see the following topics:

EjemploExample

En el siguiente ejemplo se crean tres clases que forman una cadena de herencia.The following example creates three classes that make a chain of inheritance. La clase First es la clase base, Second se deriva de First y Third se deriva de Second.The class First is the base class, Second is derived from First, and Third is derived from Second. Los tres tienen finalizadores.All three have finalizers. En Main, se crea una instancia de la clase más derivada.In Main, an instance of the most-derived class is created. Cuando ejecute el programa, observe que se llama a los finalizadores de las tres clases automáticamente y en orden, desde la más derivada hasta la menos derivada.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 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.");
    }
}

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

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

Especificación del lenguaje C#C# language specification

Para más información, vea la sección sobre destructores de la Especificación del lenguaje C#.For more information, see the Destructors section of the C# language specification.

Vea tambiénSee also