2010-12-06 17 views
54

C# tiene un constructor estático que realiza alguna inicialización. (Probablemente haga alguna inicialización de recursos no administrados) Me pregunto si hay un destilador estático?destructor estático

+1

+1 de este comentario divertido, leppie. Y me gustaría señalar que los recursos estáticos tienen en su mayoría la misma duración que la aplicación. Mueren cuando la aplicación muere. Entonces, no hay necesidad de un destructor estático. – decyclone

+2

"para que no haya necesidad de un destructor estático": ¿cómo se relacionan esas dos cosas? ¿Porque solo ocurriría cuando el appdomain se está descargando, de repente no es necesario? No estoy seguro de seguir la lógica allí. – BrainSlugs83

Respuesta

27

No, no lo hay.

Se cree que un destructor estático se ejecutará al final de la ejecución de un proceso. Cuando un proceso muere, el sistema operativo libera todas las memorias/identificadores asociados.

Si su programa debe realizar una acción específica al final de la ejecución (como un motor de base de datos transaccional, vaciar su caché), será mucho más difícil de manejar correctamente que solo un código que se ejecuta al final de la ejecución normal del proceso. Tienes que manejar manualmente los bloqueos y la finalización inesperada del proceso e intentar recuperarlos en la siguiente ejecución de todos modos. El concepto de "destructor estático" no ayudaría mucho.

+4

En mi caso, estaba usando un Mutex de todo el sistema operativo que necesitaba ser lanzado, o lanzaría una AbandonedMutexException en la siguiente ejecución de la aplicación. En este caso, la memoria y los identificadores liberados al final del programa no tuvieron en cuenta mi Mutex. Lo que usted indicó en el 3er párrafo podría ser una forma de administrarlo, pero el final del lanzamiento de la aplicación parecía tener más sentido para mí. – user1132959

10

No, no lo hay. Lo más cercano que puede hacer es establecer un controlador de eventos en el evento DomainUnload en el AppDomain y realizar su limpieza allí.

+2

Este es un enfoque muy preferido para la sugerencia de 'Process_Exit' más elevada, que es bastante diferente. La vida útil de un tipo después de que el ctor estático se ha disparado generalmente es la duración del ensamblaje, que se descarga con el AppDomain. – Abel

1

No hay nada como destructor para las clases estáticas, pero se puede utilizar Appdomain.Unloaded caso si realmente necesita hacer algo

5

Inicialización y limpieza de los recursos no administrados desde una aplicación estática es bastante problemático y propenso a problemas.

por qué no utilizar un producto único, e implementar un Finalizer para la instancia (un heredan idealmente de SafeHandle)

78
No

exactamente un destructor, pero aquí es la forma en que lo haría:

class StaticClass 
{ 
    static StaticClass() { 
     AppDomain.CurrentDomain.ProcessExit += 
      StaticClass_Dtor; 
    } 

    static void StaticClass_Dtor(object sender, EventArgs e) { 
     // clean it up 
    } 
} 
+1

perfecto. Funciona para mi. –

+1

Aunque el evento _seems_ está en AppDomain, en realidad solo se activa cuando sale el dominio predeterminado (que es el último dominio), justo antes de que se agote la aplicación. No se disparará cuando se descargue ningún otro AppDomain, lo que en sí mismo causará la destrucción de la mayoría de los tipos e instancias de tipos (pero no siempre). Este evento no está [garantizado que siempre se activará]. (Http://blogs.msdn.com/b/jmstall/archive/2006/11/26/process-exit-event.aspx). – Abel

+1

Recomiendo no dejar operaciones de limpieza delicadas hasta la deconstrucción de una instancia estática y siguiendo esta recomendación, nunca tendrá que preocuparse de que este evento no se active. Nunca tuve un problema donde este evento no se disparó (incluso cuando ocurrieron excepciones inesperadas en la aplicación).Eliminar un proceso a través del administrador de tareas es muy diferente de una excepción inesperada. Sin embargo, tiene razón, no se activará si el usuario mata el programa a través del sistema de administración de tareas del sistema operativo. –

48

Este es la mejor manera (ref: https://stackoverflow.com/a/256278/372666)

public static class Foo 
{ 
    private static readonly Destructor Finalise = new Destructor(); 

    static Foo() 
    { 
     // One time only constructor. 
    } 

    private sealed class Destructor 
    { 
     ~Destructor() 
     { 
      // One time only destructor. 
     } 
    } 
} 
+2

¡De esta forma se garantiza que funcionará! :) Pruébalo, tengo pruebas unitarias que prueban que funciona si alguien está interesado. –

+2

Confirmado. Funciona de maravilla. –

+2

¡Funcionó perfecto, muy resbaladizo! – Steve