C #에서 클래스의 소멸자와 Finalize 메서드의 차이점은 무엇입니까?


97

클래스에서 소멸자와 Finalize 메서드의 차이점은 무엇입니까?

최근에 Visual Studio 2008이 Finalize 메서드와 동의어 인 소멸자를 고려한다는 사실을 발견했습니다. 즉, Visual Studio에서는 클래스에서 두 메서드를 동시에 정의 할 수 없습니다.

예를 들어, 다음 코드 조각 :

class TestFinalize
{
    ~TestFinalize()
    {
        Finalize();
    }

    public bool Finalize()
    {
        return true;
    }
}

소멸자에서 Finalize를 호출 할 때 다음 오류를 제공합니다.

다음 메서드 또는 속성간에 호출이 모호합니다. 'TestFinalize. ~ TestFinalize ()'및 'TestFinalize.Finalize ()'

Finalize에 대한 호출이 주석 처리되면 다음 오류가 발생합니다.

'ManagementConcepts.Service.TestFinalize'유형은 이미 동일한 매개 변수 유형으로 'Finalize'라는 멤버를 정의합니다.

답변:


68

C #의 소멸자는 System.Object.Finalize메서드를 재정의 합니다. 그렇게 하려면 소멸자 구문 사용해야합니다. 수동으로 재정의 Finalize하면 오류 메시지가 표시됩니다.

기본적으로 Finalize메서드 선언 으로하려는 것은 기본 클래스의 메서드를 숨기는 것입니다. 컴파일러가 new수정자를 사용하여 음소거 할 수있는 경고를 발행하게합니다 (작동 할 경우). 여기서 주목해야 할 중요한 점은 동일한 이름을 가진 멤버를 동시에 선언 할 수 없다는 것입니다. 따라서 소멸자와 메서드 를 모두 사용 하면 오류가 발생합니다 ( 권장되지는 않지만을 선언 할 수 있습니다 .overridenewFinalizepublic new void Finalize() 경우 메서드를 수 있음). 소멸자를 선언하지 않습니다).


71

위키 백과는 종결 자와의 차이에 대한 좋은 논의가 소멸자 에서 종료자를 기사.

C #에는 실제로 "진정한"소멸자가 없습니다. 구문은 C ++ 소멸자와 비슷하지만 실제로는 종료 자입니다. 예제의 첫 번째 부분에서 올바르게 작성했습니다.

~ClassName() { }

위는 Finalize함수에 대한 구문 설탕입니다 . 기본의 종료자가 실행되도록 보장하지만 그렇지 않으면Finalize 함수 합니다. 즉, 소멸자 구문을 작성할 때 실제로 종료자를 작성하는 것입니다.

Microsoft에 따르면 종료 자는 가비지 수집기가 수집 ( Finalize) 할 때 호출하는 함수를 참조하는 반면, 소멸자는 결과로 실행되는 코드입니다 (Finalize )입니다. 그들은 마이크로 소프트가 결코 구별을하지 말았어야하는 똑같은 것에 매우 가깝습니다.

Microsoft에서 C ++의 "소멸자"용어를 사용하는 것은 잘못된 것입니다. C ++에서는 개체가 삭제되거나 스택에서 튀어 나 오자마자 동일한 스레드에서 실행되는 반면 C #에서는 다른 시간에 별도의 스레드에서 실행되기 때문입니다.


나는 소멸자와 종료 자 사이의 그러한 구별이 중요하다고 주장합니다. 그러나 후드 아래에서 일어나는 일에 관심이있는 사람들 만이 이러한 구분에 관심을 가질 것입니다.
Kyle Baran 2014 년

1
또한 ECMA-334는 오래 전에 공식적으로 "소멸자"와 "종료 자"를 명시 적으로 명확히했습니다. MS가 여전히 사양에서 잘못된 용어를 주장하는 이유를 모르겠습니다.
FrankHB

최소한 Mono로 작업하면서 C #은 실제로 C ++를 모델로하고 대부분의 네이티브 C # 개체는 C ++ 개체입니다. Mono를 컴파일 한 컴파일러가 작동하는 방식은 이러한 C ++ 개체가 소멸되는 방식과 마찬가지로 C # 개체 완료가 C ++로 전파되고 해당 소멸자를 호출하는 방식을 지시합니다. 이 구분은 내부적으로는 의미가 있지만 여전히 C # 자체에는 적용되지 않습니다.
Kenzi

20

여기에서 찾을 수 있습니다 : http://sanjaysainitech.blogspot.com/2007/06/difference-between-destructor-dispose.html

  1. 파괴 장치

    개체에 대한 정리 코드가 포함 된 특수 메서드입니다. GC에 의해 암시 적으로 호출되므로 코드에서 명시 적으로 호출 할 수 없습니다. C #에서는 ~기호가 앞에 오는 클래스 이름과 이름이 같습니다 . 처럼-

    Class MyClass
    {
    
    ~MyClass()
    {
    .....
    }
    }

    VB.NET에서 소멸자는 System.Object 클래스의 Finalize 메서드를 재정 의하여 구현됩니다.

  2. 폐기

    이것들은 클래스의 다른 메소드와 같으며 명시 적으로 호출 할 수 있지만 객체를 정리하는 특별한 목적이 있습니다. dispose 메서드에서 객체에 대한 정리 코드를 작성합니다. 데이터베이스 연결, 파일 등과 같은 dispose 메서드에서 관리되지 않는 모든 리소스를 해제하는 것이 중요합니다. dispose 메서드를 구현하는 클래스는 IDisposable 인터페이스를 구현해야합니다. 클래스는 이미 객체를 정리하기위한 작업을 수행했기 때문에 desturctor를 가지고 있습니다. 그러면 가비지 수집기가 객체의 Finalize 메서드를 호출 할 필요가 없습니다. 참조 : http://msdn2.microsoft.com/en-us/library/aa720161(VS.71).aspx

  3. 마무리

    Finalize 메서드는 Dispose 메서드가 호출되지 않은 경우 리소스를 정리하기위한 보호 장치 역할을합니다. 관리되지 않는 리소스를 정리하려면 Finalize 메서드 만 구현해야합니다. 가비지 수집기가 관리되는 리소스를 자동으로 정리하므로 관리되는 개체에 대해 Finalize 메서드를 구현하지 않아야합니다. Finalize 메서드는 GC에 의해 암시 적으로 호출되므로 코드에서 호출 할 수 없습니다.

    참고 : C #에서는 Finalize 메서드를 재정의 할 수 없으므로 내부 구현이 MSIL에서 Finalize 메서드를 재정의 할 소멸자를 사용해야하지만 VB.NET에서는 소멸자 메서드를 지원하므로 Finalize 메서드를 재정의 할 수 있습니다.

업데이트 : 여기에 흥미로운 세미 관련 스레드 .


1
You should only implement a Finalize method to clean up unmanaged resources: Finalize에 넣습니다. Dispose와 동일합니까?
hqt

@hqt : 구현해야하는 경우가 종료자를 구현해야하는 경우 Dispose보다 훨씬 많습니다. 구현 Dispose이 직접 관리되지 않는 리소스를 소유하거나 직접 직접 소유 할 수있는 마지막 일 자신의에 클래스 또는 파생 클래스의 인스턴스가 직접 관리되지 않는 리소스를 소유하거나 직접 마지막을 소유 할 수있는 마지막 일이 될 가능성이 높습니다 경우 등. Finalize자신의 클래스가 <i> 직접 </ i> 관리되지 않는 리소스를 소유하고 <i> 거의 아무것도 </ i> 소유하지 않는 경우 에만 리소스 정리를 구현 합니다 (훨씬 좁은 시나리오).
supercat 2012-06-11

@hqt : 하나의 클래스가 관리되지 않는 리소스를 직접 소유하고 다른 개체에 대한 참조도 보유하는 경우 관리되지 않는 리소스는 일반적으로 자체 종료 가능한 클래스로 분리되어야합니다 (이상적으로는 다른 항목에 대한 강력한 참조를 보유하지 않아야 함). 다른 객체에 대한 참조를 보유하는 것은 자원 자체를 소유하는 것이 아니라 "관리되지 않는 자원을 직접 소유하는 것"만을 소유하므로 종료자가 필요하지 않습니다.
supercat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.