소멸자 대 IDisposable?
C #에서 개체 / IDisposable 인터페이스 및 소멸자를 처리하는 방법에 대해 읽었지만 나에게는 동일한 작업을 수행하는 것 같습니다.
둘의 차이점은 무엇입니까? 왜 다른 하나를 사용합니까? 실제로이 예제 (아래 링크)에서이 코드는 IDisposable 인터페이스와 소멸자를 모두 사용합니다.
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
주석은 소멸자가 종료 코드를 사용하지 않는 경우라고 말합니다. 그러나 언제 다른 코드를 사용할지 어떻게 결정합니까?
종료 자, IDisposable 및 둘 중 하나를 사용해야하는시기를 설명하는 데 도움이되는 상당히 심층적 인 게시물을 작성했습니다. http://gregbee.ch/blog/implementing-and-using-the-idisposable-interface
아마도 가장 관련성이 높은 부분은 다음과 같습니다.
핸들 및 데이터베이스 연결과 같은 관리되지 않는 리소스를 사용하는 경우 늦게 획득하고 조기에 릴리스하는 원칙을 사용하여 최소 시간 동안 보유해야합니다. C ++에서 리소스 해제는 일반적으로 소멸자에서 수행되며, 이는 객체가 삭제되는 지점에서 결정적으로 실행됩니다. 그러나 .NET 런타임은 GC (가비지 수집기)를 사용하여 더 이상 연결할 수없는 개체에서 사용하는 메모리를 정리하고 회수합니다. 이것은 주기적으로 실행되기 때문에 개체가 정리되는 지점이 비 결정적임을 의미합니다. 그 결과 관리되는 개체를 실행할 결정적인 위치가 없기 때문에 소멸자가 존재하지 않습니다.
소멸자 대신 C #에는 기본 Object 클래스에 정의 된 Finalize 메서드를 재정 의하여 구현되는 종료자가 있습니다 (C #에서는 C ++ 소멸자 구문 ~ Object를 다소 혼동스럽게 사용함). 개체가 Finalize 메서드를 재정의하면 범위를 벗어 났을 때 GC에 의해 수집되지 않고 GC가이를 종료 자 대기열에 배치합니다. 다음 GC주기에서 대기열의 모든 종료자가 실행되고 (현재 구현의 단일 스레드에서) 종료 된 객체의 메모리가 회수됩니다. 이 점에서 종료 자에서 정리를 원하지 않는 이유는 상당히 분명합니다. 하나가 아닌 객체를 수집하는 데 두 개의 GC주기가 필요하며 다른 모든 스레드가 일시 중단되는 동안 모든 종료자가 실행되는 단일 스레드가 있습니다. 성능을 저하시킬 것입니다.
따라서 소멸자가없고 정리를 종료 자에게 맡기고 싶지 않은 경우 유일한 옵션은 수동으로 결정적으로 개체를 정리하는 것입니다. 이 기능을 지원하기위한 표준을 제공하고 개체에 대한 정리 논리를 입력하는 단일 메서드 인 Dispose를 정의하는 IDisposable 인터페이스를 입력합니다. finally 블록 내에서 사용되는 경우이 인터페이스는 소멸자와 동일한 기능을 제공합니다. 코드에서 finally 블록의 이유는 주로 IDisposable 인터페이스를 지원하기 때문입니다. 이것이 C ++이 소멸자가있는 finally 블록이 필요하지 않기 때문에 단순히 try / except를 사용하는 이유입니다.
짧은 버전
종료 자는 개체 사용자가을 호출하는 것을 잊은 경우 관리되지 않는 리소스를 폐기 할 수있는 기회 를 제공합니다 IDisposable.Dispose.
개체가 구현하는 경우 개체 IDisposable의 사용자가 를 호출 해야 합니다 .Dispose. 당신은하지 않습니다 이 사용자의 혼란을 정리; 하지만 좋은 일입니다.
Stackoverflow에 대한 저의 가장 인기있는 답변 은 IDisposable이있는 이유,해야 할 일, 종료자가 할 수있는 작업,하지 말아야 할 작업을 처음부터 안내합니다.
이 대답은 얼굴을 녹여
그것을 설명하는 데 사용되었습니다 : P
관리되는 프로그래밍 언어에 소멸자 (~ Object ())를 사용하는 것이 가장 간단한 아이디어입니다. C, C ++와 같은 관리되지 않는 언어가 RAII 관용구를 사용하기 때문에 소멸자를 갖는 것은 완벽하게 합리적이지만 Java, C #과 같은 관리에는 너무 터무니 없습니다.
Java Collection Framework의 전 프로젝트 책임자 인 Joshua Bloch는 Java에서 finalize () 메서드 (소멸자와 같은 C #의 C ++와 동일)라는 아이디어가 지금까지 저지른 가장 큰 실수라고 지적했습니다. C #과 마찬가지로 Java의 finallize ()는 할당 중에 finallizer 큐에 추가되어야하므로 "new"에 오버 헤드를 제공합니다. 더 나아가 가비지 콜렉터는 큐에서 finallize ()를 팝하고 실행해야하므로 gc 중에 오버 헤드가 두 배가됩니다.
C #에는 "using (IDisposable) {}"과 같은 많은 향상된 기능이있어 IDisposable 변수를 "using"블록의 범위로 제한 할뿐만 아니라 정리를 보장합니다. 내 질문은 왜 C #이 Java의 동일한 흔적을 따라 갔고 큰 실수를 초래했는지입니다. 많은 자바 아키텍트들이 finallize ()의 오류를 발견 한 2003 년 ~ 2005 년경에 dotnet 개발이 시작 되었다면 실수를 막을 수 있었을 것입니다.
한 언어에 대한 많은 좋은 아이디어는 "try (object-to-dispose) {}"문에서 Java 1.7로 전송 된 C #의 "IDisposable / using combo"와 같은 다른 언어로 전송되는 경우가 많습니다. 그러나 언어 설계자가 하나에서 다른 것으로 전환하는 동안 좋은 아이디어로 위장한 나쁜 아이디어를 발견하지 못하는 것은 너무 나쁩니다.
내 조언은 데이터베이스 연결과 같은 관리되지 않는 리소스를 수동으로 정리해야하는 경우 ~ Destructor ()를 사용하지 말고 IDisposable / using combo를 사용하는 것입니다.
참고 URL : https://stackoverflow.com/questions/456213/destructor-vs-idisposable
'Nice programing' 카테고리의 다른 글
| 파일이 유효한 UTF-8인지 확인하는 방법은 무엇입니까? (0) | 2020.11.24 |
|---|---|
| SQL Server의 매개 변수 스니핑 (또는 스푸핑) (0) | 2020.11.24 |
| gradle-다른 jar와 함께 lib dir이있는 jar를 어떻게 빌드합니까? (0) | 2020.11.24 |
| Eclipse가 Maven 종속성을 업데이트하는 데 시간이 오래 걸리는 이유는 무엇입니까? (0) | 2020.11.24 |
| 번들 설치를 실행할 때 gem 설치를위한 매개 변수를 어떻게 전달할 수 있습니까? (0) | 2020.11.24 |