소멸자를 언제 만들어야합니까?


185

예를 들면 다음과 같습니다.

public class Person
{
    public Person()
    {
    }

    ~Person()
    {
    }
}

언제 소멸자를 수동으로 만들어야합니까? 소멸자를 언제 만들어야 했습니까?


1
C # 언어는 이러한 "소멸자"를 호출하지만 대부분의 사람들은 .NET 이름이므로 "완료 자"라고하며 C ++ 소멸자와의 혼동을 줄입니다 (매우 다릅니다). 3 명 쉬운 규칙 :는 IDisposable 및 종료 자 구현하는 방법
스티븐 클리어 리

5
무모하다고 느낄 때.
capdragon

32
TomTom의 키보드가 고장 났다고 생각합니다. 캡 잠금 장치가 산발적으로오고있었습니다. 기묘한.
Jeff LaFay


나는 Greg Beech의 제안에 따라 소멸자를 디버깅 보조 도구로 사용했습니다 : stackoverflow.com/questions/3832911/…
Brian

답변:


237

업데이트 :이 질문은 2015 년 5 월 내 블로그의 주제였습니다 . 좋은 질문 감사합니다! 사람들이 일반적으로 마무리에 대해 믿는 많은 허위 목록은 블로그를 참조하십시오.

언제 소멸자를 수동으로 만들어야합니까?

거의 없다.

일반적으로 클래스가 객체가 사라질 때 정리해야하는 고가의 관리되지 않는 리소스를 보유하고있을 때 소멸자를 만듭니다. 자원을 정리하려면 일회용 패턴을 사용하는 것이 좋습니다. 그러면 소멸자는 객체의 소비자가 폐기하는 것을 잊어 버린 경우에도 리소스가 결국 정리된다는 보증입니다. (아마도.)

소멸자 를 매우 조심스럽게 만들고 가비지 수집기가 작동하는 방식을 이해하는 경우 . 소멸자는 정말 이상합니다 :

  • 그들은 스레드에서 실행되지 않습니다. 그들은 자신의 스레드에서 실행됩니다. 교착 상태를 유발하지 마십시오!
  • 소멸자로부터 처리되지 않은 예외가 발생하면 나쁜 소식입니다. 자체 스레드에 있습니다. 누가 잡을까요?
  • 생성자가 시작된 생성자가 완료 되기 전에 객체에서 소멸자가 호출 될 수 있습니다 . 올바르게 작성된 소멸자는 생성자에 설정된 불변에 의존하지 않습니다.
  • 소멸자는 객체를 "복구"하여 죽은 객체를 다시 살릴 수 있습니다. 정말 이상합니다. 하지마
  • 소멸자는 절대 도망 가지 않을 것입니다. 완료 예정인 개체에 의존 할 수 없습니다. 아마 그럴 입니다, 그러나 그것은 보증이 아닙니다.

소멸자에서 일반적으로 사실 인 것은 거의 없습니다. 정말 조심하세요. 올바른 소멸자를 작성하는 것은 매우 어렵습니다.

소멸자를 언제 만들어야 했습니까?

소멸자를 처리하는 컴파일러 부분을 테스트 할 때. 나는 프로덕션 코드에서 그렇게 할 필요가 없었습니다. 관리되지 않는 리소스를 조작하는 개체는 거의 작성하지 않습니다.


"생성자가 시작된 후 생성자가 끝나기 전에 객체에서 소멸자가 호출 될 수 있습니다." 그러나 필드 초기화 프로그램을 사용하여 실행할 수 있습니다.
구성자

13
@configurator : 아뇨. 정적 메소드라고하는 종료자가있는 객체의 세 번째 필드 이니셜 라이저에서 예외가 발생했다고 가정하십시오. 네 번째 필드 이니셜 라이저는 언제 실행됩니까? 못. 그러나 개체는 여전히 할당되어 있으며 마무리되어야합니다. 도저가 실행될 때 double 유형의 필드가 완전히 초기화 되었다는 보장조차 없습니다 . 더블을 작성하는 도중에 스레드 중단이 있었을 수 있으며 이제 파이널 라이저는 반 초기화 된 반 제로 더블을 처리해야합니다.
Eric Lippert

1
훌륭한 게시물이지만 "클래스가 고가의 관리되지 않는 개체를 보유하거나 많은 수의 관리되지 않는 개체가 존재할 때 생성되어야합니다."라고 말해야합니다. 구체적인 예를 들어 C #에 기본 네이티브 C ++를 사용하는 행렬 클래스가 있습니다. 무거운 많이 할 수있는 매트릭스 클래스 - 나는 행렬을 많이 만들 - 더 나은 동기화 집의 관리 및 관리되지 않는 측면을 유지하기 때문에 "소멸자"이 특정의 경우는 IDisposable 훨씬 우수하다
마크 멀린

1
pythonnet 관리되지 않는 CPython과의 GIL을 해제 소멸자를 사용
denfromufa

3
멋진 기사 Eric. 이것에 대한 제안-> "추가 보너스 재미 : 런타임은 디버거에서 프로그램을 실행할 때 덜 공격적인 코드 생성과 덜 가비지 수집을 사용합니다. 디버깅 경험이 있기 때문에 디버깅하는 객체가 갑자기 사라져도 개체를 참조하는 변수의 범위가 좁습니다. 즉, 개체가 너무 일찍 마무리되는 버그가 있으면 디버거에서 해당 버그를 재현 할 수 없습니다. "
Ken Palmer

17

이를 "완료 자"라고하며 일반적으로 상태 (예 : 필드)에 관리되지 않는 리소스 (예 : p / invoke 호출을 통해 검색된 핸들에 대한 포인터)가 포함 된 클래스에 대해 하나만 작성해야합니다. 그러나 .NET 2.0 이상에서는 실제로 관리되지 않는 리소스 정리를 처리하는 더 좋은 방법 인 SafeHandle이 있습니다. 이를 감안할 때, 파이널 라이저를 다시 작성할 필요는 없습니다.


25
@ThomasEding- 그렇습니다 . C #은 소멸자 구문을 사용하지만 실제로 finalizer를 생성합니다 . 다시 .
JDB는 여전히 Monica

@JDB : 언어 구조를 소멸 자라고합니다 . 나는 그 이름을 싫어하지만 그것이 바로 그 이름입니다. 소멸자를 선언하면 컴파일러가 소멸자 본문에 나타나는 것과 함께 약간의 래퍼 코드를 포함하는 종료 자 메서드를 생성합니다.
supercat

8

클래스가 Windows 파일 핸들과 같은 관리되지 않는 리소스를 유지 관리하지 않는 한 필요하지 않습니다.


5
사실, 그것은 소멸
자라고합니다

2
이제 혼란 스러워요. 종료 자 또는 소멸자입니까?

4
C # 사양에서는 실제로이를 소멸 자라고합니다. 어떤 사람들은 이것을 실수라고 생각합니다. stackoverflow.com/questions/1872700/…
Ani

2
@ThomasEding- 그렇습니다 . C #은 소멸자 구문을 사용하지만 실제로 finalizer를 생성합니다 .
JDB는 여전히 Monica

2
나는 여기에 의견을 좋아한다, 진짜 판토 :)
Benjol

4

소멸자 / 완료 기라고하며 일반적으로 Disposed 패턴을 구현할 때 생성됩니다.

클래스의 사용자가 Dispose를 호출하는 것을 잊어 버리고 (최종적으로) 리소스가 해제되도록하는 소멸 솔루션이지만 소멸자가 호출되는 시점에 대한 보장은 없습니다.

스택 오버플로 질문 에서 허용 된 답변은 폐기 패턴을 구현하는 방법을 올바르게 보여줍니다. 가비지 수집기가 자체 정리하지 않는 처리되지 않은 리소스가 클래스에 포함 된 경우에만 필요합니다.

좋은 방법은 클래스의 사용자에게 리소스를 수동으로 처리하여 리소스를 즉시 해제 할 수있는 가능성을 부여하지 않고 종료자를 구현하지 않는 것입니다.


실제로 C #에서는 소멸자로 불리지 않습니다.
TomTom

14
실제로 입니다. 당신이 착각했기 때문에 공감대를 주셔서 감사합니다. 이 특정 문제와 관련된 MSDN 라이브러리를 참조하십시오. msdn.microsoft.com/en-us/library/66x5fx1b.aspx
Øyvind Bråthen

1
@TomTom 공식 이름은 소멸자입니다
David Heffernan

실제로 폴백 방법이 아니라 개체가 관리되지 않는 리소스를 확보 할 때 GC가 관리 할 수 ​​있도록하며 IDisposable을 구현하면 직접 관리 할 수 ​​있습니다.
HasaniH

3

관리되지 않는 리소스가 있고 개체가 없어 질 때 리소스가 정리되도록해야합니다. COM 개체 또는 파일 처리기가 좋은 예입니다.


2

객체를 WPF 응용 프로그램 범위의 메모리에서 제거했는지 확인하기 위해 소멸자 (디버그 목적으로 만)를 사용했습니다. 가비지 수집이 실제로 개체를 메모리에서 제거하는지 확실하지 않았으므로 확인하는 것이 좋습니다.


1

소멸자는 클래스에 캡슐화되어있는 관리되지 않는 리소스를 해제하는 암시 적 방법을 제공합니다. GC가 리소스를 가져 오면 호출되며 기본 클래스의 Finalize 메서드를 암시 적으로 호출합니다. 관리되지 않는 많은 리소스를 사용하는 경우 IDisposable 인터페이스를 통해 해당 리소스를 해제하는 명시적인 방법을 제공하는 것이 좋습니다. C # 프로그래밍 가이드를 참조하십시오 : http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.