[c#] IDisposable 개체 참조가 삭제되었는지 어떻게 알 수 있습니까?

참조가 삭제 된 객체에 대한 것인지 확인하는 방법 또는 다른 가벼운 방법이 있습니까?

추신-이것은 단지 호기심입니다 (프로덕션 코드가 아니라 잘 자십시오). 예, ObjectDisposedException객체의 멤버에 액세스하려고 할 때를 잡을 수 있다는 것을 알고 있습니다 .



답변

아니오-IDisposable 패턴의 기본 구현이이를 지원하지 않습니다.


답변

System.Windows.Forms.ControlIsDisposed되는 재산 후 true로 설정 Dispose()호출됩니다 . 고유 한 IDisposable 개체에서 유사한 속성을 쉽게 만들 수 있습니다.


답변

이것을 허용하는 내장 된 것은 없습니다. 내부 삭제 플래그를 반영하는 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);
    }
}


답변

그것이 당신의 클래스가 아니고 IsDisposed 속성 (또는 비슷한 것-이름은 단지 관례 일뿐)을 제공하지 않는다면, 당신은 알 수있는 방법이 없습니다.

그러나 그것이 당신의 클래스이고 표준 IDisposable 구현을 따르는 경우 _disposed 또는 _isDisposed 필드를 속성으로 노출하고 확인하십시오.


답변

Dispose메서드는 개체를 버리기 전에 필요한 정리를 수행하는 데 필요합니다. 정리가 필요하지 않은 경우 아무것도 수행 할 필요가 없습니다. Dispose메서드가 아무 작업도하지 않더라도 객체가 폐기되었는지 여부를 추적하도록 요구하려면 IDisposable매우 제한적인 이점을 위해 많은 객체가 플래그를 추가해야합니다.

IDisposable두 가지 속성을 포함 하면 도움이되었을 것입니다. 하나는 객체를 폐기 해야하는지 여부를 표시 하고 하나는 객체가 폐기 로 인해 쓸모 없게 렌더링 되지 않았 음을 나타냅니다 . 처리가 실제로 어떤 작업을 수행하는 객체의 경우 두 값 모두 처음에는 true이고 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