Как определить, расположена ли ссылка на объект IDisposable? - PullRequest
80 голосов
/ 10 октября 2008

Есть ли способ или какой-нибудь другой легкий способ проверить, является ли ссылка на удаленный объект?

P.S. - Это просто любопытство (спи спокойно, а не в производственном коде). Да, я знаю, что могу поймать ObjectDisposedException при попытке получить доступ к члену объекта.

Ответы [ 8 ]

44 голосов
/ 10 октября 2008

Нет - реализация шаблона IDisposable по умолчанию не поддерживает его

38 голосов
/ 10 октября 2008

System.Windows.Forms.Control имеет свойство IsDisposed, которое установлено в значение true после того, как Dispose() вызвано . В ваших собственных объектах IDisposable вы можете легко создать похожее свойство.

18 голосов
/ 17 октября 2008

Нет встроенного ничего, что позволило бы это. Вам необходимо предоставить логическое свойство IsDisposed, которое отражает внутренний флаг удаления.

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);
    }
}
9 голосов
/ 10 октября 2008

Если это не ваш класс и он не предоставляет свойство IsDisposed (или что-то похожее - это просто соглашение), то у вас нет возможности узнать.

Но если это ваш класс, и вы следуете за канонической реализацией IDisposable , то просто выставьте поле _disposed или _isDisposed в качестве свойства и проверьте это.

2 голосов
/ 08 октября 2015

Метод Dispose необходим для выполнения любой необходимой очистки перед тем, как объект будет оставлен; если очистка не требуется, ничего делать не требуется. Требование к объекту отслеживать, был ли он удален, даже если метод Dispose в противном случае ничего бы не сделал, потребует много объектов IDisposable для добавления флага для очень ограниченной выгоды.

Возможно, было бы полезно, если бы IDisposable включал два свойства - одно из которых указывало, нужно ли объекту распоряжаться , и одно из них указывало, что объект не был лишен возможности по распоряжению. Для объектов, где удаление действительно что-то делает, оба значения будут изначально истинными и станут ложными после Dispose. Для объектов, для которых удаление не требует какой-либо очистки, первый метод всегда может возвращать false, а второй всегда true, без необходимости хранить флаг где-либо. Однако я не думаю, что теперь они могут быть добавлены в .NET.

1 голос
/ 14 сентября 2018

Я вижу, что это старо, но я не видел ответа. Некоторые не все одноразовые объекты, такие как DataSet, имеют событие удаления, которое можно прикрепить.

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;
    }
}
0 голосов
/ 08 декабря 2013

Что мне нравится делать, так это объявлять объекты без их инициализации, но устанавливать их значения по умолчанию Nothing. Затем в конце цикла я пишу:

If anObject IsNot Nothing Then anObject.Dispose()

Вот полный пример:

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

Это также отлично подходит для размещения ваших главных объектов в верхней части процедуры, использования их внутри процедуры Try, а затем размещения их в блоке Finally:

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
0 голосов
/ 10 октября 2008

Зависит от того, что есть IDisposable объекты, которые позволяют вызывать метод Dispose столько, сколько вы хотите, и есть IDisposable объекты, которые выбрасывают ObjectDisposedException. В таком случае эти объекты должны отслеживать состояние (обычно реализуемое с помощью частного логического поля isDisposed).

...