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


85

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

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


11
Dunno. 에 대한 bool IsDisposed { get; }선언 이없는 것이 궁금해 보입니다 System.IDisposable.
nicodemus13 2012 년

3
@ nicodemus13 :이 Dispose메서드는 획득했지만 아직 해제하지 않은 모든 리소스를 해제하도록 개체에 지시합니다. 객체가 자원을 보유하지 않는 경우 해당 Dispose메소드는 일반적으로 아무것도 할 필요가 없습니다. 유형이 선언 void IDisposable.Dispose() {};하면 IDisposable인스턴스 당 오버 헤드없이 무시할 수 있습니다 . 호출 후 IsDisposed참이 될 것으로 예상 되는 속성은 . DisposeDispose
supercat

1
그러나를 구현하는 객체에서 메서드를 호출 할 때마다 IDisposable먼저 폐기되었는지 여부를 어떻게 확인할 수 있습니까? 그렇지 않다고 가정하고 예외를 잡는 대신? 아니면 어떻게 든 당신은 그것이 폐기되었는지 여부를 항상 알아야 할 수 있도록 평생을 관리해야합니까?
nicodemus13

3
@ nicodemus13 : 일반적으로 객체가 처리되지 않았고 처리되지 않을 것이라는 사실을 알지 못한 채 객체를 사용해서는 안됩니다. 단, 외부 코드에 의한 객체 처리를 보류중인 작업을 중단하라는 신호로 간주 할 준비가 된 경우를 제외하고는 . IsDisposed플래그는 코드가 성공할 수없는 작업에 시간을 낭비하는 것을 방지 하는 데 도움이 될 수 있지만 IsDisposed검사와 사용 시도 사이에 개체가 삭제되는 경우 예외를 처리해야 합니다.
supercat

WeakReference여기에 관련이있는 것 같습니다. 그것은 정확히 IDipose'd 검출기 아니지만,이 GC'd 있다면 그것은 당신을 말해 주는가
말라기

답변:


47

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


41

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


OP는 그가 생성하지 않는 객체에 이미 유사한 속성이 있는지 확인하려고했습니다. 이것은 우리가 만드는 개체에 대한 좋은 생각이지만 .NET의 대부분의 일회용 클래스는이 규칙을 따르지 않습니다. Dandikas의 대답이 맞습니다.
krillgar

2
@krillgar, OP의 질문에 귀하의 주장을 뒷받침하는 것은 없습니다.
Ryan Lundy

18

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

BTW,이 패턴을 사용하기 시작하면에서 IDisposablePlus상속 IDisposable하고 포함 하는 새 인터페이스 ( 또는 기타) 를 정의하는 데 도움이 됩니다 bool IsDisposed { get; }. 이렇게하면 어떤 IDisposable개체가를 지원 하는지 쉽게 알 수 있습니다 IsDisposed.
ToolmakerSteve

C #의 작동 방식 때문에 인터페이스를 상속 할 수 없다고 생각합니다. 콜론 뒤에 인터페이스를 배치하면 상속됩니다. 다른 인터페이스를 구현할 것으로 예상합니다.
Moses

9

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

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


2

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

IDisposable두 가지 속성을 포함 하면 도움이되었을 것입니다. 하나는 객체를 폐기 해야하는지 여부를 표시 하고 하나는 객체가 폐기 로 인해 쓸모 없게 렌더링 되지 않았 음을 나타냅니다 . 처리가 실제로 어떤 작업을 수행하는 객체의 경우 두 값 모두 처음에는 true이고 Dispose. 처리 할 때 정리할 필요가없는 개체의 경우 첫 번째 메서드는 항상 false를 반환하고 두 번째 메서드는 플래그를 어디에도 저장할 필요없이 항상 true를 반환 할 수 있습니다. 하지만 지금은 .NET에 추가 할 수있는 방법이 없다고 생각합니다.


IMHO, 두 개의 플래그는 과잉입니다. Dispose가 개체에 대해 호출되면 하나의 플래그가있는 일반적인 패러다임을 고수하는 것이 더 낫다고 생각합니다. 그렇지 않으면 Dispose가 호출되었지만 특정 개체가 "여전히 유용"하다는 것을 알기 위해 복잡성을 추가합니다. 그 길을 갈 가치가 없습니다.
ToolmakerSteve

@ToolmakerSteve : 일반적으로 0 개 또는 1 개의 플래그가 있습니다. 폐기가 필요한 객체의 경우 "needs disposing"및 "is useful"속성은 폐기 전에 "true / true"를, 이후에는 "false / false"를 생성하지만, 폐기가 no-op 인 객체의 경우 둘 다 무조건적으로 생성됩니다. "false / true"를 반환합니다. 객체가 결코 처리되지 않을 때 여전히 처분이 필요하거나 객체가 항상 유용 할 때 유용하지 않다고 말하는 것은 다소 어색 할 것입니다. 또 다른 접근 방식은 열거 형을 사용하여 유형이 폐기되어야하는지, 폐기되었는지 또는 단순히 신경 쓰지 않는지를 나타내는 것입니다.
supercat

@ToolmakerSteve : 속성이 IDisposable없는 가장 큰 이유 는 Disposed호출 Dispose이 이러한 속성을로 설정하지 않는 객체를 갖는 것이 이상하다고 인식되었을 true것이지만 해당 객체가 다음과 같은 Dispose경우 호출 되었는지 여부를 추적하도록 요구했기 때문 이라고 생각 합니다 그렇지 않으면 돌볼 이유가 없을 것이며 상당한 비용을 추가하고 거의 이익을 얻지 못할 것입니다.
supercat

1

나는 이것이 오래된 것을 보았지만 대답을 보지 못했습니다. 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;
    }
}

알아 둘만 한. 특히 Disposed이벤트는 System.ComponentModel.IComponent인터페이스 의 구성원입니다 .
ToolmakerSteve

-1

내가 좋아하는 것은 초기화하지 않고 객체를 선언하지만 기본값을 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

6
@ LarsHöppner : 질문의 본질은 언어에 구애받지 않습니다. 훌륭한 C # 개발자는 위 코드를 읽을 수있을만큼 VB.NET을 알고 있어야합니다 (그리고 VB.NET 개발자는 그렇지 않은 C # 코드를 읽을 수있을만큼 충분한 C #을 배워야합니다. 특히 이국적인 것을하십시오).
supercat

3
Using성명 을 사용하는 대신이 모든 작업을 수행하는 이유는 무엇 입니까? 이 답변이 작성되었을 때 2013 년에 확실히 존재했습니다.
Cody Gray

정말 "GoodExit :"GOTO의 1983 년은 무엇입니까 ?? 그 사용을 중지하십시오.
모세

이것은 질문에 대한 답이 아닙니다. 구체적으로, inputPdf값 (Nothing 이외)으로 설정 되면 답변 inputPdf이 폐기 되었는지 여부를 알 수있는 방법이 없습니다 . 폐기 후 설정하여 부분적으로 해결할 수 inputPdf = Nothing있습니다. 그러나 이것은와 동일한 객체를 가리키는 다른 변수 에는 도움이되지 않습니다 inputPdf. : 그것은 당신이 할 경우입니다 inputPdf = New PdfReader, Dim pdf2 As PdfReader = inputPdf, inputPdf.Dispose, inputPdf = Nothing, 여전히 알 수있는 방법이 없을 것입니다 pdf2(이 같은 목적에 배치된다 inputPdf).
ToolmakerSteve
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.