소멸자가 아닌 클래스에서 IDispose를 언제 구현합니까? 이 기사를 읽었 지만 여전히 요점이 누락되었습니다.
내 가정은 객체에 IDispose를 구현하면 가비지 수집기가 수행하기를 기다리는 대신 명시 적으로 ‘파괴’할 수 있다는 것입니다. 이 올바른지?
객체에 대해 항상 명시 적으로 Dispose를 호출해야 함을 의미합니까? 이에 대한 일반적인 예는 무엇입니까?
답변
종료 자 (소멸자라고도 함)는 가비지 수집 (GC)의 일부입니다. GC는 주로 메모리 부족 (즉, 더 많은 공간이 필요함)의 결과로 발생하기 때문에 이것이 발생하는시기 (또는 발생하더라도) 불확실합니다. 종료자는 일반적으로 정리에만 사용됩니다. 관리되지 않는 리소스 관리되는 리소스에는 자체 수집 / 처리가 있기 때문입니다.
그 후 IDisposable
객체 를 결정적으로 정리하는 데 사용됩니다 . 객체의 메모리 (여전히 GC에 속해 있음)를 수집하지 않지만 예를 들어 파일, 데이터베이스 연결 등을 닫는 데 사용됩니다.
이에 대한 이전 주제가 많이 있습니다.
마지막으로, IDisposable
객체가 종료 자를 갖는 것은 드문 일이 아닙니다 . 이 경우 Dispose()
일반적으로를 호출합니다 GC.SuppressFinalize(this)
. 즉, GC는 종료자를 실행하지 않고 메모리를 버립니다 (훨씬 저렴). Dispose()
객체 를 잊어 버린 경우에도 종료자가 계속 실행됩니다 .
답변
Finalize()
메서드 의 역할은 가비지 수집시 .NET 개체가 관리되지 않는 리소스를 정리할 수 있도록하는 것 입니다. 그러나 데이터베이스 연결 또는 파일 처리기와 같은 개체는 가비지 수집에 의존하는 대신 가능한 한 빨리 해제해야합니다. 이를 위해 IDisposable
인터페이스 를 구현 하고 Dispose()
메서드 에서 리소스를 해제해야합니다 .
답변
MSDN 에 대한 매우 좋은 설명이 있습니다 .
이 인터페이스의 주요 용도는 관리되지 않는 리소스 를 해제하는 것 입니다. 가비지 수집기 는 해당 개체가 더 이상 사용되지 않을 때 관리되는 개체에 할당 된 메모리를 자동으로 해제합니다 . 그러나 가비지 콜렉션이 언제 발생할지 예측할 수 없습니다 . 또한 가비지 수집기 는
창 핸들이나 열린 파일 및 스트림과 같은 관리되지 않는 리소스에 대한 지식이 없습니다 .이 인터페이스의 Dispose 메서드를 사용하여
가비지 수집기와 함께 관리되지 않는 리소스 를 명시 적으로 해제 합니다. 개체 의
소비자는 개체가 더 이상 필요하지 않을 때이 메서드를 호출 할 수 있습니다.
답변
C # 소멸자에 있어야하는 유일한 것은 다음 줄입니다.
Dispose(False);
그게 다야. 그 방법에는 다른 것이 없어야합니다.
답변
항상 전화해야하는지 여부에 대한 질문 Dispose
은 일반적으로 열띤 논쟁입니다. .NET 커뮤니티에서 존경받는 개인의 흥미로운 관점을 보려면 이 블로그를 참조하십시오 .
개인적으로 전화 Dispose
가 필수가 아니라는 Jeffrey Richter의 입장 은 엄청나게 약하다고 생각합니다. 그는 자신의 의견을 정당화하기 위해 두 가지 예를 제공합니다.
첫 번째 예에서 그는 Dispose
Windows Forms 컨트롤을 호출 하는 것이 주류 시나리오에서 지루하고 불필요하다고 말합니다 . 그러나 그는 Dispose
이러한 주류 시나리오에서 실제로 제어 컨테이너에 의해 자동으로 호출 된다는 점을 언급하지 않았습니다.
두 번째 예에서 그는 개발자가 IAsyncResult.WaitHandle
속성이 대기 핸들을 느리게 초기화하여 불필요한 성능 저하를 초래한다는 사실을 깨닫지 않고 인스턴스 가 공격적으로 처리되어야 한다고 잘못 가정 할 수 있다고 말합니다 . 그러나이 예제의 문제점은 그 IAsyncResult
자체가 IDisposable
개체 처리에 대한 Microsoft의 자체 게시 지침을 준수하지 않는다는 것 입니다. 즉, 클래스가 IDisposable
유형에 대한 참조를 보유하고 있으면 클래스 자체가 IDisposable
. IAsyncResult
그 규칙을 따를 경우 자체 Dispose
방법으로 구성 구성원 중 어느 쪽을 폐기해야하는지 결정할 수 있습니다.
따라서 누군가가 더 설득력있는 주장을하지 않는 한, 저는 대부분 잘못된 디자인 선택으로 인해 발생하는 몇 가지 부가적인 사례가있을 것이라는 이해와 함께 “항상 Dispose를 호출”캠프에 머물 것입니다.
답변
정말 간단합니다. 답변을 받았지만 다시 시도하지만 가능한 한 간단하게 유지하려고 노력할 것입니다.
일반적으로 소멸자는 사용하지 않아야합니다. .net이 실행되기를 원합니다. 가비지 수집주기 후에 만 실행됩니다. 애플리케이션의 수명주기 동안에는 실제로 실행되지 않을 수 있습니다. 따라서 ‘반드시’실행해야하는 소멸자에 코드를 넣지 마십시오. 또한 클래스가 실행될 때 존재하는 기존 개체에 의존 할 수 없습니다 (소멸자가 실행되는 순서가 보장되지 않으므로 이미 정리되었을 수 있음).
정리가 필요한 리소스 (예 : 파일 및 그래픽 핸들)를 생성하는 개체가있을 때마다 IDisposible을 사용해야합니다. 사실, 많은 사람들은 소멸자에 넣은 모든 것이 위에 나열된 이유로 인해 IDisposable해야한다고 주장합니다.
대부분의 클래스는 종료자가 실행될 때 dispose를 호출하지만 이것은 단순히 안전 가드로서 존재하며 절대로 의존해서는 안됩니다. 작업이 끝나면 IDisposable을 구현하는 모든 것을 명시 적으로 폐기해야합니다. IDisposable을 구현하는 경우 종료 자에서 dispose를 호출해야합니다. 예제는 http://msdn.microsoft.com/en-us/library/system.idisposable.aspx 를 참조 하십시오 .
답변
다음은 IDisposable, GC 및 dispose를 둘러싼 안개를 제거하는 또 다른 훌륭한 기사입니다.