.NET Framework Dispose () vs. finalizers


Exemple

Implémentez la méthode Dispose () (et déclarez la classe contenant comme IDisposable) pour vous assurer que toutes les ressources dont la mémoire est lourde sont libérées dès que l'objet n'est plus utilisé. Le "catch" est qu’il n’ya pas de garantie forte que la méthode Dispose () soit invoquée (contrairement aux finaliseurs qui sont toujours appelés à la fin de la vie de l’objet).

Un scénario est un programme appelant Dispose () sur les objets qu'il crée explicitement:

private void SomeFunction()
{
    // Initialize an object that uses heavy external resources
    var disposableObject = new ClassThatImplementsIDisposable();

    // ... Use that object

    // Dispose as soon as no longer used
    disposableObject.Dispose();

    // ... Do other stuff 

    // The disposableObject variable gets out of scope here
    // The object will be finalized later on (no guarantee when)
    // But it no longer holds to the heavy external resource after it was disposed
}

Un autre scénario consiste à déclarer une classe instanciée par le framework. Dans ce cas, la nouvelle classe hérite généralement d'une classe de base. Par exemple, dans MVC, une classe de contrôleur est créée en tant que sous-classe de System.Web.Mvc.ControllerBase. Lorsque la classe de base implémente l'interface IDisposable, il s'agit d'une bonne indication que Dispose () serait correctement invoqué par le framework, mais là encore, il n'y a pas de garantie forte.

Ainsi, Dispose () ne remplace pas un finaliseur; au lieu de cela, les deux devraient être utilisés à des fins différentes:

  • Un finaliseur libère éventuellement des ressources pour éviter les fuites de mémoire qui se produiraient autrement
  • Dispose () libère les ressources (éventuellement les mêmes) dès que celles-ci ne sont plus nécessaires, pour alléger la pression sur l'allocation globale de la mémoire.