Existe-t-il une méthode, ou un autre moyen léger, pour vérifier si une référence est à un objet supprimé?
PS - C'est juste une curiosité (dormez bien, pas dans le code de production). Oui, je sais que je peux attraper le ObjectDisposedException
en essayant d'accéder à un membre de l'objet.
c#
.net
dispose
idisposable
Neil C. Obremski
la source
la source
bool IsDisposed { get; }
déclaration surSystem.IDisposable
.Dispose
méthode demande à un objet de libérer toutes les ressources qu'il a acquises mais pas encore libérées. Si un objet ne contient jamais de ressources, saDispose
méthode n'aura généralement rien à faire; si le type le déclare,void IDisposable.Dispose() {};
il peut sinon ignorerIDisposable
sans surcharge par instance. UneIsDisposed
propriété qui devait devenir vraie après unDispose
appel nécessiterait l'ajout d'un indicateur booléen autrement inutile à chaque instance de nombreux types qui pourraient autrement être ignorésDispose
.IDisposable
, comment pouvez-vous vérifier si elle a été éliminée en premier? Plutôt que de supposer que ce n'est pas le cas et d'attraper une exception? Ou d'une manière ou d'une autre, vous êtes censé gérer la vie de manière à toujours savoir si elle est éliminée ou non?IsDisposed
indicateur peut aider à empêcher le code de perdre du temps sur des opérations qui ne peuvent pas réussir, mais il faudrait quand même gérer des exceptions dans le cas où un objet serait éliminé entre laIsDisposed
vérification et la tentative de l'utiliser.WeakReference
semble pertinent ici. Ce n'est pas exactement un détecteur IDipose'd, mais il vous dit s'il est GC'dRéponses:
Non - l'implémentation par défaut du modèle IDisposable ne le prend pas en charge
la source
System.Windows.Forms.Control
a uneIsDisposed
propriété définie sur true après l'Dispose()
appel . Dans vos propres objets IDisposable, vous pouvez facilement créer une propriété similaire.la source
Il n'y a rien de intégré qui permette cela. Vous devez exposer une propriété booléenne IsDisposed qui reflète un indicateur supprimé interne.
public class SimpleCleanup : IDisposable { private bool disposed = false; public bool IsDisposed { get { return disposed; } } public SimpleCleanup() { this.handle = /*...*/; } protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // free only managed resources here } // free unmanaged resources here disposed = true; } } public void Dispose() { Dispose(true); } }
la source
IDisposablePlus
ou autre) qui hérite deIDisposable
et inclutbool IsDisposed { get; }
. Cela permet de savoir facilement lesquels de vosIDisposable
objets prennent en chargeIsDisposed
.Si ce n'est pas votre classe et qu'elle ne fournit pas de propriété IsDisposed (ou quelque chose de similaire - le nom n'est qu'une convention), alors vous n'avez aucun moyen de le savoir.
Mais si c'est votre classe et que vous suivez l' implémentation canonique d'IDisposable , alors exposez simplement le champ _disposed ou _isDisposed en tant que propriété et vérifiez cela.
la source
La
Dispose
méthode est requise pour effectuer tout nettoyage requis avant qu'un objet ne soit abandonné; si aucun nettoyage n'est requis, il n'est pas nécessaire de faire quoi que ce soit. Exiger qu'un objet garde une trace de sa suppression, même lorsque laDispose
méthode ne ferait autrement rien, exigerait que de nombreuxIDisposable
objets ajoutent un indicateur pour un bénéfice très limité.Il aurait peut-être été utile d'
IDisposable
inclure deux propriétés - l'une indiquant si un objet devait être éliminé et l'autre indiquant que l'objet n'avait pas été rendu inutile par l'élimination. Pour les objets où l'élimination fait réellement quelque chose, les deux valeurs seraient initialement vraies et deviendraient fausses par la suiteDispose
. Pour les objets où l'élimination n'a pas besoin de faire de nettoyage, la première méthode peut toujours retourner false et la seconde toujours true, sans avoir à stocker un indicateur n'importe où. Cependant, je ne pense pas qu'il soit possible de les ajouter à .NET maintenant.la source
IDisposable
n'y a pas deDisposed
propriété est qu'il aurait été perçu comme étrange d'avoir des objets sur lesquels l'appelDispose
ne définirait pas une telle propriététrue
, mais exigeant que les objets gardent une trace de l'Dispose
appel dans les cas où autrement, ils n'auraient aucune raison de s'en soucier, ce qui ajouterait des coûts importants et peu d'avantages.Je vois que c'est vieux, mais je n'ai pas vu de réponse. Certains objets jetables comme un DataSet n'ont pas tous un événement supprimé que vous pouvez attacher.
class DisposeSample : IDisposable { DataSet myDataSet = new DataSet(); private bool _isDisposed; public DisposeSample() { // attach dispose event for myDataSet myDataSet.Disposed += MyDataSet_Disposed; } private void MyDataSet_Disposed(object sender, EventArgs e) { //Event triggers when myDataSet is disposed _isDisposed = true; // set private bool variable as true } public void Dispose() { if (!_isDisposed) // only dispose if has not been disposed; myDataSet?.Dispose(); // only dispose if myDataSet is not null; } }
la source
Disposed
événement est un membre de l'System.ComponentModel.IComponent
interface.Ce que j'aime faire, c'est déclarer les objets sans les initialiser, mais définir leurs valeurs par défaut sur
Nothing
. Puis, à la fin de la boucle, j'écris:If anObject IsNot Nothing Then anObject.Dispose()
Voici un échantillon complet:
Public Sub Example() Dim inputPdf As PdfReader = Nothing, inputDoc As Document = Nothing, outputWriter As PdfWriter = Nothing 'code goes here that may or may not end up using all three objects, ' such as when I see that there aren't enough pages in the pdf once I open ' the pdfreader and then abort by jumping to my cleanup routine using a goto .. GoodExit: If inputPdf IsNot Nothing Then inputPdf.Dispose() If inputDoc IsNot Nothing Then inputDoc.Dispose() If outputWriter IsNot Nothing Then outputWriter.Dispose() End Sub
Cela fonctionne également très bien pour mettre vos objets principaux au sommet d'une routine, les utiliser dans une
Try
routine, puis les disposer dans unFinally
bloc:Private Sub Test() Dim aForm As System.Windows.Forms.Form = Nothing Try Dim sName As String = aForm.Name 'null ref should occur Catch ex As Exception 'got null exception, no doubt Finally 'proper disposal occurs, error or no error, initialized or not.. If aForm IsNot Nothing Then aForm.Dispose() End Try End Sub
la source
Using
instruction? Cela existait certainement en 2013, lorsque cette réponse a été rédigée.inputPdf
défini sur une valeur (autre que Nothing), votre réponse ne montre aucun moyen de savoir si elleinputPdf
a été supprimée. Vous pouvez en partie résoudre ce problème en définissantinputPdf = Nothing
après l'élimination. Cependant, cela n'aiderait pas les autres variables qui ont été pointées vers le même objet queinputPdf
. C'est si vous le faites:inputPdf = New PdfReader
,Dim pdf2 As PdfReader = inputPdf
,inputPdf.Dispose
,inputPdf = Nothing
, il y aurait encore aucun moyen de savoir quipdf2
est disposé (il est le même objet queinputPdf
).