2008-11-01 9 views
36

¿Cuál es la forma correcta de realizar una finalización estática?Finalizador estático

No hay un destructor estático. El evento AppDomain.DomainUnload no se genera en el dominio predeterminado. El evento AppDomain.ProcessExit comparte el tiempo total de los tres segundos (configuración predeterminada) entre todos los controladores de eventos, por lo que no es realmente utilizable.

+2

Primero, en C#, tenemos que dejar el hábito de usar el finalizador y el destructor de forma intercambiable. Uno es determinista, el otro no. Es interesante observar que la especificación C# obtiene los términos hacia atrás de CLR y otras especificaciones de lenguaje .NET.También es interesante observar que las notas del comité de lenguaje C# dicen explícitamente que no hay razones previstas por las cuales C# no puede tener finalizadores estáticos. http://stackoverflow.com/a/1875149/56793 – JMD

Respuesta

27

Básicamente, no se puede. Diseña tu camino a su alrededor en la mayor medida posible.

No olvide que un programa puede siempre terminar de forma abrupta de todos modos - alguien sacando la potencia es el ejemplo obvio. Entonces, cualquier cosa que hagas tiene que ser "el mejor esfuerzo", en cuyo caso yo ciertamente espero que que AppDomain.ProcessExit sería lo suficientemente bueno.

¿Qué necesitas hacer, en tu caso particular?

+1

¿Cómo se relaciona esta respuesta con la respuesta de Michael (dado que parece que es posible tener finalizadores estáticos)? (De cualquier forma estoy de acuerdo en que los finalizadores no son confiables.) – mafu

+0

@mafutrct: La respuesta de Michael no es realmente un finalizador estático. Es un campo estático con una referencia a una instancia que tiene un finalizador. No es lo mismo, aunque podría tener efectos similares. No lo usaría personalmente –

+0

En realidad, tienes toda la razón. ¡Gracias por la explicación! – mafu

6

Me gustaría cuestionar lo que está cargando en sus métodos estáticos que deben ser liberados. Ciertamente, no recomendaría hacer estas cosas en un método estático.

Dicho esto, su método estático podría instanciar un objeto que tiene un método de finalización.

6

Dos soluciones que saltan a la mente:

  • no utilice una clase estática. Si utilizas una clase no estática e instancias, no tienes que preocuparte tanto por la limpieza.
  • Si esa no es una opción, yo diría que esta es una buena situación para usar un singleton. Esto creará una instancia de una copia de su objeto y le pedirá que lo haga al finalizador, pero aún así le permitirá tratarlo como una clase estática en su mayor parte. Después de todo, su clase ya está estática y, por lo tanto, comparte la mayoría de las razones comunes para no utilizar un singleton.
39

Herfried Wagner ha escrito un excellent article explicar cómo implementar esto - por desgracia, en alemán (y VB). Aún así, el código debe ser comprensible.

Lo he intentado:

static readonly Finalizer finalizer = new Finalizer(); 

sealed class Finalizer { 
    ~Finalizer() { 
    Thread.Sleep(1000); 
    Console.WriteLine("one"); 
    Thread.Sleep(1000); 
    Console.WriteLine("two"); 
    Thread.Sleep(1000); 
    Console.WriteLine("three"); 
    Thread.Sleep(1000); 
    Console.WriteLine("four"); 
    Thread.Sleep(1000); 
    Console.WriteLine("five"); 
    } 
} 

Parece que funciona exactamente de la misma manera que lo hace el evento AppDomain.ProcessExit: el finalizador se ca. tres segundos ...

+3

Esta es la mejor respuesta ya que puede depurar su "finalizador" de esta manera, mientras que el dominio de la aplicación. El delegado ProcessExit no te permite depurarlo (al menos en mi experiencia). –

0

Copiar la respuesta de Michael Damatov (C#) que se basa en Herfried K. Wagner. (VB.NET) aquí está la versión de C++/CLI:

ref class MyClass 
{ 
     ref class StaticFinalizer sealed 
     { 
      !StaticFinalizer(); 
     }; 
     static initonly StaticFinalizer^ stDestr = gcnew StaticFinalizer(); 
} 

MyClass::StaticFinalizer::!StaticFinalizer() 
{ 
    System::Diagnostics::Debug::WriteLine("In StaticFinalizer!"); 
} 

P.S. Al igual que el método AppDomain.ProcessExit, este no se puede invocar si el proceso finaliza anormalmente (desde el Administrador de tareas, por ejemplo). Otra advertencia es que si MyClass es genérico (con plantilla), la suposición de que su constructor estático y su destructor estático no se invocarán más de una vez por ejecución de la aplicación ya no será válida.

Cuestiones relacionadas