41 votes

Comment et quand les membres statiques de c# sont-ils disposés ?

J'ai une classe avec de nombreux membres statiques, dont certains gardent des références à des objets gérés et non gérés.

Par exemple, le constructeur statique est appelé dès que le Type est référencé, ce qui entraîne la création d'une file d'attente bloquante de Tasks dans ma classe. Cela se produit lorsque l'une des méthodes statiques est appelée, par exemple.

J'ai implémenté IDisposable, qui me donne des méthodes pour gérer l'élimination des objets d'instance que j'ai créés. Cependant, ces méthodes ne sont jamais appelées si le consommateur ne crée aucun objet d'instance de ma classe.

Comment et où dois-je placer le code pour éliminer les références maintenues par la partie statique de ma classe ? J'ai toujours pensé que l'élimination des ressources référencées statiques se produisait lorsque le dernier objet d'instance était libéré ; c'est la première fois que je crée une classe dans laquelle aucune instance ne peut être créée.

61voto

dasblinkenlight Points 264350

Les variables statiques de votre classe ne sont pas collectées jusqu'à ce que le domaine d'application hébergeant votre classe soit déchargé. Le site Dispose() ne sera pas appelée, car il s'agit d'une méthode d'instance, et vous avez dit que vous ne créeriez pas d'instances de votre classe.

Si vous souhaitez utiliser le Dispose() faites de votre objet un singleton, créez-en une instance et débarrassez-vous-en explicitement lorsque votre application est sur le point de se terminer.

public class MyClass : IDisposable {
    public IList List1 {get; private set;}
    public IDictionary<string,string> Dict1 {get; private set;}
    public void Dispose() {
        // Do something here
    }
    public static MyClass Instance {get; private set;}
    static MyClass() {
        Instance = new MyClass();
    }
    public static void DisposeInstance() {
        if (Instance != null) {
            Instance.Dispose();
            Instance = null;
        }
    }
}

9voto

Guido Kleijer Points 52
public class Logger : IDisposable
{

    private string _logDirectory = null;
    private static Logger _instance = null;

    private Logger() : this(ConfigurationManager.AppSettings["LogDirectory"])
    {
        AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
    }

    private Logger(string logDirectory) 
    {
    } 

    public static Logger Instance
    {
        get
        {
            if (_instance == null)
                _instance = new Logger();
            return _instance;
        }
    }

    private void CurrentDomain_ProcessExit(object sender, EventArgs e)
    {
        Dispose();
    }

    public void Dispose()
    {
        // Dispose unmanaged resources
    }
}

0voto

oxilumin Points 2894

Vous devez disposer de ces objets manuellement, il n'existe aucun moyen de créer un "finalisateur" pour les ressources statiques.

-1voto

ilias iliadis Points 131

Si vous voulez vraiment avoir des membres statiques qui gardent des références à des objets non gérés créez simplement une méthode pour disposer des objets non gérés et "forcez" le consommateur à l'utiliser à la sortie.

Par "forcer", j'entends documenter votre classe avec un paragraphe qui indique "quand" et "pourquoi" utiliser cette méthode "dispose". Faites-le si vous êtes le seul consommateur (ou votre code...) ou si vous prévoyez de distribuer votre classe. Essayez également d'utiliser un nom descriptif (pour cette méthode "dispose") tel que "DisposeStatics", "AlwaysDispose", "DisposeAtEnd", etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X