Как узнать, удалена ли ссылка на объект IDisposable?

StackOverflow https://stackoverflow.com/questions/192206

  •  08-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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);
    }
}

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

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

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

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

Вижу, это старо, но ответа я не увидел.Некоторые не все одноразовые объекты, такие как 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;
    }
}

Мне нравится объявлять объекты без их инициализации, но устанавливать для них значения по умолчанию: 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top