IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Destructeur toujours appellé ?


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Par défaut Destructeur toujours appellé ?
    Bonjour, je voudrais savoir si dans certains cas le destructeur (dispose) n'était pas appeller alors même que l'objet serait supprimer de la mémoire ?

    Par exemple, si considérant un site en ASP.Net, j'ai dans ma session utilisateur un objet de classe X. Les dll du site, dont celles qui définissent la classe X sont mises à jour sur le serveur. Lorsque ma session devrait être lue, l'object de l'ancienne classe X n'est plus lisible (vu que la classe a "disparue" au profit d'une nouvelle version). Est-ce que dans ce cas par exemple, je suis certain que la méthode dispose (de la classe disparue) sera appellée ?

    Cela est essentiel pour faire certains cleanup DB.


    Merci aux 1000 premiers à répondre ainsi qu'au suivants.

  2. #2
    Membre chevronné Avatar de Redouane
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    435
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 435
    Par défaut
    Bonjour,

    Ce que je sais c'est que lorsqu'un objet abandonne la portée, il est libéré par le Common Language Runtime (CLR).
    il faut savoir que le GarbageCollector a pour but de libérer la mémoire des objets qui ne sont plus référencés dans le programme au cours de son exécution.

    Tu peux trouver ton besoin dans cet article de msdn :
    http://msdn.microsoft.com/fr-fr/library/hks5e2k6.aspx

    Je ne l'ai pas tt lu

    Cdt,

  3. #3
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    En C# les destructeurs sont toujours appelés. La seule inconnue, c'est de savoir à quel moment ils le seront. Après, il y a plusieurs manières :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    class X
    { 
       ...
       ~X()
       {
          //toujours appelé
       }
    }
     
    class X : IDisposable
    { 
       ...
       ~X()
       {
          //toujours appelé
       }
     
       public void Dispose()
       {
          //appelé s'il y a un appel explicite à Dispose ou que l'instance de X est utilisée via un using(){}
       }
    }
     
    class X : IDisposable
    { 
       ...
       ~X()
       {
          //toujours appelé
          Dispose(false);
       }
     
       bool disposed = false;
     
       private void Dispose(bool disposing)
       {
          //toujours appelé au minimum 1 fois (peut être appelé plusieurs fois)
          if(!this.disposed)
          {
              disposed = true;
              //grâce à la condition, on ne passe ici qu'une fois dans la vie de l'objet
     
              if(disposing)
              {
                 //appelé lors d'un appel explicite à Dispose ou un blog using(){}
              }
              else
              {
                 //appelé lorsque l'objet meurt via le destructeur ~X()
              }
          }
       }
     
       public void Dispose()
       {
          //appelé s'il y a un appel explicite à Dispose ou que l'instance de X est utilisée via un using(){}
          Dispose(true);
       }
    }

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    en résumé

    pour les classes du framework, aucune question à se poser, on peut appeler dispose, et dispose sera forcément appelé si on ne l'a pas fait car finalize l'appelera

    tant qu'on écrit des classes .net, aucune question à se poser, il ne sert à rien d'implémenter IDisposable

    après si tu écris des choses non managées il faut bien lire le pattern de IDisposable avec overrides du finalize

    (on est encore loin des 1000 mais y a de la pointure)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre expérimenté
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Par défaut
    Citation Envoyé par sperot51 Voir le message
    pour les classes du framework, aucune question à se poser, on peut appeler dispose, et dispose sera forcément appelé si on ne l'a pas fait car finalize l'appelera
    Sauf qu'il y a une question à se poser : la classe possède-t-elle une méthode Dispose ? Si oui il faut libérer explicitement lorsque l'objet n'est plus utile (appel de la méthode Dispose) afin d'aider le GC à faire son travail correctement. J'ai déjà vu des problèmes parce que la personne n'appelait pas les Dispose en se disant que de toute façon le GC se chargera de gérer tout ça.

    Je pense que c'est une règle qu'il faut appliquer, sans se poser de question cette fois. Le premier réflexe à avoir c'est de regarder si une méthode Dispose existe lorsque l'on ne connait pas la classe que l'on utilise (généralement il y aura une méthode Close aussi, les deux donnant le même résultat). Ensuite le second réflexe c'est d'appeler Dispose dès lors que l'objet n'est plus utile.

    Citation Envoyé par sperot51 Voir le message
    tant qu'on écrit des classes .net, aucune question à se poser, il ne sert à rien d'implémenter IDisposable
    Je dis non car on peut écrire des classes .Net qui possèdent des membres implémentant IDisposable (un Stream ou une collection d'images par exemple) et à ce moment il faut implémenter IDisposable.

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par sperot51 Voir le message
    pour les classes du framework, aucune question à se poser, on peut appeler dispose, et dispose sera forcément appelé si on ne l'a pas fait car finalize l'appelera
    Il vaut mieux appeler quand-même Dispose explicitement : si on ne le fait pas, effectivement ce sera finalement appelé par le destructeur, sauf qu'on ne sait pas quand le destructeur sera appelé : il n'y a pas moyen de prévoir quand le GC va collecter l'objet, ça peut aussi bien être dans 30 secondes que dans 10h. Si l'objet est couteux en RAM, utilise des ressources système ou bloque l'accès à un fichier, tu as tout intérêt à faire un Dispose dessus le plus tôt possible...

    Citation Envoyé par sperot51 Voir le message
    tant qu'on écrit des classes .net, aucune question à se poser, il ne sert à rien d'implémenter IDisposable
    Bien sûr que si ! En fait, la règle que j'essaie d'appliquer est la suivante : dès qu'une de mes classes a des champs dont le type implémente IDisposable, j'implémente aussi IDisposable pour libérer ces objets.
    Il y a aussi d'autres cas d'utilisation de IDisposable, par exemple pour créer un "scope" avec un block using. Cela permet de s'assurer que le code de "nettoyage" du scope est bien efffectué à la fin du block using

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    destructeur (dispose)
    Attention, le destructeur (ou Finalize) et la méthode Dispose sont 2 choses différentes ! Dispose sert, au départ, à libérer les ressources non-managées utilisées par un objet (même si par la suite on s'est rendu compte que ça pouvait servir à plein d'autres choses, notamment grâce à l'instruction using). Dispose n'est pas automatiquement appelé par le GC quand l'objet est collecté : il faut l'appeler explicitement dans le destructeur (méthode Finalize pour les langages qui n'ont pas de syntaxe pour le destructeur).

    Pour plus de détails et un exemple d'implémentation typique de IDisposable, va voir ce lien

    Citation Envoyé par Sergejack Voir le message
    Bonjour, je voudrais savoir si dans certains cas le destructeur (dispose) n'était pas appeller alors même que l'objet serait supprimer de la mémoire ?
    En cas de plantage "violent" (genre plantage du CLR, ce qui est assez rare), le destructeur ne sera pas appelé. Dans tous les autres cas, le GC se charge d'appeler automatiquement le destructeur sur les objets qui ne sont plus référencés. Par contre ça n'implique pas forcément un appel à Dispose, cf. ma remarque plus haut.

    Quand le process s'arrête, toute la mémoire qu'il utilisait est de toute façon libérée, que les destructeurs aient été appelés ou non.

    Citation Envoyé par Sergejack Voir le message
    Par exemple, si considérant un site en ASP.Net, j'ai dans ma session utilisateur un objet de classe X. Les dll du site, dont celles qui définissent la classe X sont mises à jour sur le serveur. Lorsque ma session devrait être lue, l'object de l'ancienne classe X n'est plus lisible (vu que la classe a "disparue" au profit d'une nouvelle version). Est-ce que dans ce cas par exemple, je suis certain que la méthode dispose (de la classe disparue) sera appellée ?

    Cela est essentiel pour faire certains cleanup DB.
    Je pense que ça dépend, entre autres, de comment tu gères tes sessions. Avec l'option par défaut (InProcess), les sessions sont conservées en mémoire, il n'y a donc pas besoin de sérialisation. Si tu utilises un autre mode de stockage des sessions (base de données, fichiers...), effectivement ça peut sans doute poser un problème...

    Quand tu remplaces tes assemblies par une version plus récente, ça provoque le redémarrage de l'application, mais avant le redémarrage la version actuelle de l'assembly est encore en mémoire : tu peux donc sans doute exécuter du code pour gérer proprement l'arrêt de l'application (dans les évènements Application_End et Session_End par exemple)

Discussions similaires

  1. Réponses: 9
    Dernier message: 30/11/2007, 11h15
  2. Réponses: 2
    Dernier message: 12/07/2007, 10h12
  3. destructeur pas appelé ?
    Par NiamorH dans le forum C++
    Réponses: 28
    Dernier message: 27/04/2007, 16h20
  4. Réponses: 9
    Dernier message: 07/10/2006, 10h54
  5. [destructeur] [pas appelé]
    Par Gonath dans le forum C++
    Réponses: 11
    Dernier message: 23/02/2006, 18h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo