2010-12-06 7 views
54

C# a un constructeur statique qui effectue une initialisation. (Probablement faire une initialisation de ressource non managée) Je me demande s'il y a un destuctor statique?destructeur statique

+1

+1 pour ce drôle de commentaire, leppie. Et je voudrais souligner que les ressources statiques ont la plupart du temps la même durée de vie que l'application. Ils meurent quand l'application meurt. Donc, il n'y a pas besoin d'un destructeur statique. – decyclone

+2

"donc il n'y a pas besoin d'un destructeur statique" - comment ces deux choses sont-elles liées? Parce que cela ne se produirait que lorsque l'appdomain serait déchargé, ce n'est plus nécessaire? Je ne suis pas sûr de suivre la logique ici. – BrainSlugs83

Répondre

27

Non, il n'y en a pas.

Un destructeur statique serait supposé fonctionner à la fin de l'exécution d'un processus. Quand un processus meurt, toutes les mémoires/poignées associées sont libérées par le système d'exploitation. Si votre programme doit effectuer une action spécifique à la fin de l'exécution (comme un moteur de base de données transactionnel, vider son cache), il sera beaucoup plus difficile de gérer correctement qu'un simple code qui court à la fin de l'exécution normale du processus. Vous devez gérer manuellement les plantages et les interruptions inattendues du processus et essayer quand même de les récupérer à la prochaine exécution. Le concept de «destructeur statique» n'aiderait pas beaucoup.

+4

Dans mon cas, j'utilisais un Mutex à l'échelle du système d'exploitation qui avait besoin d'être libéré, ou il émettait une exception AbandonedMutexException lors de la prochaine exécution de l'application. Dans ce cas, la mémoire et les poignées libérées à la fin du programme ne rendaient pas compte de mon Mutex. Ce que vous avez indiqué dans le troisième paragraphe pourrait être un moyen de le gérer, mais une fin de la version de l'application semblait avoir plus de sens pour moi. – user1132959

10

Non, il n'y en a pas. La chose la plus proche que vous pouvez faire est de définir un gestionnaire d'événements à l'événement DomainUnload sur le AppDomain et y effectuer votre nettoyage.

+2

Il s'agit en fait d'une approche beaucoup plus préférée de la suggestion 'Process_Exit' dont la valeur est plus élevée, ce qui est assez différent. La durée de vie d'un type après le démarrage de ctor statique est généralement la durée de vie de l'assembly, qui est déchargée avec AppDomain. – Abel

1

Non, il n'y a rien comme destructor pour les classes statiques mais vous pouvez utiliser l'événement Appdomain.Unloaded si vous avez vraiment besoin de faire quelque chose

5

et nettoyage Initialiser des ressources non gérés à partir d'une mise en œuvre statique est très problématique et sujette à des problèmes.

Pourquoi ne pas utiliser un singleton, et mettre en œuvre un Finalizer pour l'instance (un hériteront idéalement de SafeHandle)

78

Pas exactement un destructor, mais voici comment vous le faire:

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

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

parfait. Travaille pour moi. –

+1

Bien que l'événement apparaisse sur AppDomain, il est en fait uniquement déclenché lorsque le domaine par défaut se termine (c'est-à-dire, le dernier domaine), juste avant que toute l'application ne meurt. Il ne se déclenchera pas lorsque tout autre AppDomain sera déchargé, ce qui entraînera la destruction de la plupart des types et des instances de types (mais pas toujours). Cet événement n'est pas [garanti pour toujours tirer.] (Http://blogs.msdn.com/b/jmstall/archive/2006/11/26/process-exit-event.aspx). – Abel

+1

Je recommande de ne pas laisser les opérations de nettoyage sensibles jusqu'à la déconstruction d'une instance statique et suite à cette recommandation, vous n'aurez jamais besoin de vous inquiéter que cet événement ne se déclenche pas. Je n'ai jamais eu un problème où cet événement n'a pas eu lieu (même si des exceptions inattendues dans l'application ont eu lieu).Tuer un processus via le gestionnaire de tâches est très différent d'une exception inattendue. Vous avez raison cependant, il ne se déclenchera pas si l'utilisateur tue le programme via le système de gestion des tâches du système d'exploitation. –

48

Cette est le meilleur moyen (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 cette façon est garanti de travailler! :) Essayez-le, j'ai des tests unitaires qui prouvent que cela fonctionne si quelqu'un est intéressé? –

+2

Confirmé. Fonctionne comme un charme. –

+2

A travaillé parfait, très lisse! – Steve

Questions connexes