Comment disposer des ressources gérées dans la méthode Dispose () en C #?
Je sais Dispose() est destiné à des ressources non managées, et les ressources doivent être éliminés lorsqu'il n'est plus nécessaire, sans attendre pour le garbage collector pour finaliser l'objet.
Cependant, lors de l'élimination de l'objet, c'supprimer la finalisation du garbage collector (GC.SuppressFinalize(ce); dans le code ci-dessous). Cela signifie que si l'objet comprend les ressources gérées, nous aurons à prendre soin de ce aussi parce que le garbage collector ne sera pas nettoyer cette.
Dans l'exemple de code ci-dessous (à partir de MSDN), "Composant" est une ressource gérée, et nous appelons dispose() pour cette ressource (composant.Dispose()). Ma question est, comment pouvons-nous mettre en œuvre cette méthode pour la classe de Composant qui est géré de ressources? Devrions-nous utiliser quelque chose comme Collect() pour pousser garbage collector pour nettoyer cette partie?
Toute idée serait la bienvenue. Merci.
Ci-dessous est le code je suis à la recherche de ce qui est à partir de MSDN:
using System;
using System.ComponentModel;
//The following example demonstrates how to create
//a resource class that implements the IDisposable interface
//and the IDisposable.Dispose method.
public class DisposeExample
{
//A base class that implements IDisposable.
//By implementing IDisposable, you are announcing that
//instances of this type allocate scarce resources.
public class MyResource: IDisposable
{
//Pointer to an external unmanaged resource.
private IntPtr handle;
//Other managed resource this class uses.
private Component component = new Component();
//Track whether Dispose has been called.
private bool disposed = false;
//The class constructor.
public MyResource(IntPtr handle)
{
this.handle = handle;
}
//Implement IDisposable.
//Do not make this method virtual.
//A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
//This object will be cleaned up by the Dispose method.
//Therefore, you should call GC.SupressFinalize to
//take this object off the finalization queue
//and prevent finalization code for this object
//from executing a second time.
GC.SuppressFinalize(this);
}
//Dispose(bool disposing) executes in two distinct scenarios.
//If disposing equals true, the method has been called directly
//or indirectly by a user's code. Managed and unmanaged resources
//can be disposed.
//If disposing equals false, the method has been called by the
//runtime from inside the finalizer and you should not reference
//other objects. Only unmanaged resources can be disposed.
private void Dispose(bool disposing)
{
//Check to see if Dispose has already been called.
if(!this.disposed)
{
//If disposing equals true, dispose all managed
//and unmanaged resources.
if(disposing)
{
//Dispose managed resources.
component.Dispose();
}
//Call the appropriate methods to clean up
//unmanaged resources here.
//If disposing is false,
//only the following code is executed.
CloseHandle(handle);
handle = IntPtr.Zero;
//Note disposing has been done.
disposed = true;
}
}
//Use interop to call the method necessary
//to clean up the unmanaged resource.
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
//Use C# destructor syntax for finalization code.
//This destructor will run only if the Dispose method
//does not get called.
//It gives your base class the opportunity to finalize.
//Do not provide destructors in types derived from this class.
~MyResource()
{
//Do not re-create Dispose clean-up code here.
//Calling Dispose(false) is optimal in terms of
//readability and maintainability.
Dispose(false);
}
}
public static void Main()
{
//Insert code here to create
//and use the MyResource object.
}
}
source d'informationauteur elios786 | 2010-02-17
Vous devez vous connecter pour publier un commentaire.
Ce qui est faux. Le garbage collector toujours nettoyer vos ressources gérées. Les finaliseurs sont également strictement pour le nettoyage de ressources non managées, et donc la SuppressFinalize() l'appel ne vous blessera pas.
Et puisque vous êtes nouveau à la IDisposable modèle je vais anticiper votre prochain point de prêter à confusion: l'écriture finaliseurs. En C#, vous ne devriez écrire un finaliseur lorsque vous traitez avec un tout nouveau type de ressource non managée. Donc, si vous avez, par exemple, une classe qui encapsule le Système.Les données.SqlClient.SqlConnection type dans le cadre d'une couche d'accès aux données, vous devez pas écrire un finaliseur pour ce type parce que vous êtes toujours aux prises avec le même type de sous-jacent non géré type de ressource: base de données sql server connexions. Le finaliseur pour que des ressources est pris en charge par la base de SqlConnection type.
D'autre part, si vous êtes à la construction d'un ADO.Net fournisseur pour un tout nouveau type de moteur de base de données, vous devrez mettre en œuvre un outil de finalisation dans votre classe de connexion, car qui n'a jamais été fait avant.
Que jetables modèle est déroutant. Voici une meilleure façon à mettre en œuvre:
L'étape 1. Créer une classe jetables pour encapsuler chaque client de ressources que vous avez. Cela doit être très rare, la plupart des gens n'ont pas les ressources non managées à nettoyer. Cette classe seul soucis (pdf) sur sa ressource non managée, et devrait avoir un finaliseur. La mise en œuvre ressemble à ceci:
L'étape 2. Créer une classe jetables lorsque le groupe détient d'autres jetable classes. Simple à mettre en œuvre, vous n'avez pas besoin d'un outil de finalisation. Dans votre méthode dispose, il suffit d'appeler la Jeter sur les autres consommables. Vous n'avez pas de soins sur les ressources non managées dans ce cas:
Le "Composant" dans l'exemple serait l'un de ceux-ci, selon qu'il encapsule une ressource non managée ou si elle n'est composée que d'autres ressources jetables.
Également noter que supressing finalisation ne signifie pas que vous êtes la suppression de la collecte des déchets provenant du nettoyage de votre instance; cela signifie simplement que lorsque le garbage collector s'exécute dans votre exemple, il ne sera pas appeler le finaliseur définie.
Peut-être un peu plus clair. GC.SuppressFinalize(ce) n'affecte que l'objet référencé par le pointeur this, mais pas à tous les membres de l'objet. C'est-à-dire que SuppressFinalize ne pas appliquer récursivement pour les membres de l'objet. Lorsque le Garbage Collector libère la mémoire pour l'objet supprimé, il est probable qu'il n'y aura pas de références actives pour les objets les champs. Puisque vous n'avez pas appeler GC.SuppressFinalize sur tous les champs de l'objet, puis le Garbage Collector qui fera appel à la méthode finalize sur ces objets, s'ils existent. Lorsqu'il le fait c'est complètement jusqu'à l'exécution et, en général, vous devriez vous suffit de laisser faire sa chose.
Désolé si j'ai mal compris votre question!!, mais si votre classe a référencé pour d'autres classes, et ces références à ces objets n'ont pas besoin de disposer votre classe n'est pas nécessairement nee pour mettre en œuvre IDisposable.