[c#] C #에서 IDisposable과 소멸자를 사용하는 것의 차이점은 무엇입니까?

소멸자가 아닌 클래스에서 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의 입장 은 엄청나게 약하다고 생각합니다. 그는 자신의 의견을 정당화하기 위해 두 가지 예를 제공합니다.

첫 번째 예에서 그는 DisposeWindows 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를 둘러싼 안개를 제거하는 또 다른 훌륭한 기사입니다.

Chris Lyons WebLog Demystifying Dispose