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();  
    }  
}  

Este diseño 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 design 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; es el recolector de elementos no utilizados el que decide cuándo hacerlo.The programmer has no control over when the finalizer is called; the garbage collector decides when to call it. 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 si se llama a Collect, pero debe evitarse esta llamada porque puede dar lugar a problemas de rendimiento.It's possible to force garbage collection by calling Collect, but most of the time, this call 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 por parte del desarrollador como los lenguajes que no están diseñados para un runtime con recolección de elementos no utilizados.In general, C# does not require as much memory management on the part of the developer as languages that don't target a runtime with garbage collection. Esto es debido a que el recolector de elementos no utilizados de .NET administra implícitamente la asignación y liberación de memoria para los objetos.This is because the .NET 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 liberar el recurso, implemente un método Dispose desde la interfaz IDisposable que realiza la limpieza necesaria del objeto.To release the resource, implement 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. Aun con este control explícito sobre los recursos, el finalizador se convierte en una salvaguarda para limpiar recursos si se produce un error en la llamada al método Dispose.Even with this explicit control over resources, the finalizer becomes a safeguard to clean up resources if the call to the Dispose method fails.

Para obtener más información sobre la limpieza de recursos, vea los siguientes artículos:For more information about cleaning up resources, see the following articles:

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 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.
*/

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