Quel est le but de remplacer Dispose (bool disposing) dans .NET?

Si j’écris une classe en C # qui implémente IDisposable, pourquoi ne suffit-il pas de simplement implémenter

public void Dispose(){ ... } 

gérer la libération de ressources non gérées?

Est

 protected virtual void Dispose(bool disposing){ ... } 

toujours nécessaire, parfois nécessaire ou autre chose?

Ce n’est pas ssortingctement nécessaire. Il fait partie du modèle jetable recommandé. Si vous n’avez pas lu la section «Framework Design Guidelines» à ce sujet (9.3 dans la première édition, la deuxième édition n’est pas utile, désolé), alors vous devriez le faire. Essayez ce lien .

Il est utile de faire la distinction entre le nettoyage jetable et la collecte des ordures-finalisable.

Vous n’êtes pas obligé de le faire de cette façon mais vous devriez le lire et comprendre pourquoi cela est recommandé avant de le considérer comme inutile.

Le schéma complet, y compris un finaliseur, l’introduction d’une nouvelle méthode virtuelle et le “scellement” de la méthode de repository d’origine, est très général et couvre toutes les bases.

Sauf si vous avez des descripteurs directs sur des ressources non gérées (qui ne devraient presque jamais être ), vous n’avez pas besoin d’un finaliseur.

Si vous scellez votre classe (et que mes vues sur les classes de scellement sont autant que possible connues à l’heure actuelle – conception pour l’inheritance ou l’interdire ), il est inutile d’introduire une méthode virtuelle.

Je ne peux pas me souvenir de la dernière fois que j’ai implémenté IDisposable d’une manière “compliquée” par rapport à la manière la plus évidente, par exemple

 public void Dispose() { somethingElse.Dispose(); } 

Une chose à noter est que si vous optez pour du code vraiment robuste, vous devez vous assurer que vous n’essayez pas de faire quoi que ce soit après avoir été éliminé, et lancer ObjectDisposedException cas échéant. C’est un bon conseil pour les bibliothèques de classes qui seront utilisées par les développeurs du monde entier, mais il y a beaucoup de travail pour très peu de gain si cela doit simplement être une classe utilisée dans votre propre espace de travail.

Il y a un peu de partialité dans les documents MSFT sur le modèle jetable. Vous devez mettre en œuvre IDisposable pour deux raisons:

  1. Vous avez des champs d’un type qui implémente IDisposable
  2. Vous avez un finalizer.

Le cas 1 est assez commun dans la plupart des codes. Le cas 2 est assez commun dans le code écrit par Microsoft, ce sont eux qui ont écrit les wrappers gérés autour des ressources non managées, celles qui doivent être finalisées. Mais devrait être très rare dans votre code. Après tout, vous avez toutes ces belles classes .NET pour faire le sale boulot pour vous. Vous devez simplement appeler leurs méthodes Dispose ().

Seul le cas 2 nécessite le modèle jetable. Microsoft doit l’utiliser beaucoup. Vous aurez juste besoin du simple Dispose () la plupart du temps.

En plus des autres bonnes réponses, vous pouvez vérifier ces articles:

  • Implémentation du modèle IDisposable et du modèle Dispose correctement
  • IDisposable: ce que votre mère ne vous a jamais dit à propos de la répartition des ressources (principe de conception jetable)

La méthode supplémentaire avec la disposition de bool est sortie d’une directive de conception de cadre quelque part. C’est simplement un modèle permettant à votre classe de pouvoir appeler la méthode dispose plusieurs fois sans lancer une exception. Ce n’est pas absolument nécessaire. Techniquement, vous pouvez le faire dans la méthode disposer.

Juste pour développer ce que d’autres ont dit: ce n’est pas simplement que vous n’avez pas besoin de «disposition complexe», mais que vous ne le voulez pas , pour des raisons de performance.

Si vous allez sur la route ‘complex dispose’ et implémentez un finaliseur, puis oubliez de jeter explicitement votre object, votre object (et tout ce qu’il fait référence) survivra à une génération de GC supplémentaire avant qu’il ne soit réellement disposé (puisqu’il doit en contourner un) plus de temps pour que le CLR appelle le finaliseur). Cela provoque juste plus de pression de mémoire que vous n’avez pas besoin. De plus, l’appel du finaliseur sur tout un tas d’objects a un coût non négligeable.

Donc, évitez, à moins que vous (ou vos types dérivés) ayez des ressources non gérées.

Oh, et pendant que nous sums dans le coin: les méthodes de votre classe qui gèrent les événements des autres doivent être «sûres» face à l’invocation après la suppression de votre classe. Le plus simple est de simplement effectuer une no-op si la classe est éliminée. Voir http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

Une des choses que cela vous donne est la possibilité de travailler dans Dispose () sans rapport avec la finalisation, tout en nettoyant les ressources non managées.

Faire quelque chose sur un object géré autre que “yourself” dans un finaliseur est extrêmement … imprévisible. Cela est dû en grande partie au fait que vos finaliseurs seront appelés à l’étape 2 de l’arrêt de votre AppDomain de manière non déterministe – donc, lorsque votre finaliseur est appelé, il est fort probable que des objects auxquels vous avez encore des références ont déjà été finalisé.

Dissortingbuer les appels Dispose et finalizer à la même méthode vous permet de partager votre code d’arrêt, tandis que le paramètre booléen vous permet d’ignorer le nettoyage géré, le cas échéant.

En outre, la virtualité de la méthode offre aux héritiers un moyen simple d’append leur propre code de nettoyage, avec un risque moindre de ne pas appeler le vôtre par inadvertance.

Si une classe implémente IDisposable.Dispose() et qu’une classe dérivée doit append une logique supplémentaire, cette classe doit exposer une sorte de méthode Dispose laquelle la classe dérivée peut être liée. Comme certaines classes peuvent implémenter IDisposable.Dispose() sans avoir une méthode publique Dispose() , il est utile d’avoir une méthode virtuelle qui sera protected dans toutes les implémentations d’ IDisposable qu’elles aient ou non une méthode publique Dispose . Dans la plupart des cas, l’argument bool n’est pas vraiment significatif mais doit être considéré comme un argument factice pour que la protected virtual Dispose(bool) ait une signature différente de Dispose() .

Les classes qui n’utilisent pas un object protected virtual Dispose(bool) nécessiteront des classes dérivées pour gérer leur logique de nettoyage d’une manière différente de la convention. Certains langages tels que C ++ / CLI, qui ne sont équipés que pour étendre les implémentations IDisposable qui suivent cette convention, peuvent être incapables de dériver des classes d’implémentations non standard.