C# 클래스 소멸자 ~ (물결 문자)

😢 이 페이지는 다음 주소로 변경될 예정입니다.

C#을 쓸 일이 종종 있는데 아직 초보 수준이라서 모르는 문법이 많다. 코드를 읽다가 메서드 선언 앞에 나온 물결 문자를 보게 되었는데 관련된 내용을 찾아봤다. 다음 내용은 함수명 앞에 오는 물결 표시는 무슨 의미인가요?에 나온 답변이다.

C#에서 메소드 선언 앞에 나오는 ~(물결 문자, 틸드)는 소멸자다.

  • 소멸자는 자동으로 동작하며 명시적으로 실행할 수 없다.
  • 소멸자는 오버로드가 불가능하다. 그러므로 클래스는 최대 하나의 소멸자를 가질 수 있다.
  • 소멸자는 상속되지 않는다. 그러므로 클래스는 하나 이외의 소멸자를 가지지 않게 되고 그 소멸자는 해당 클래스에서 선언이 되어야만 한다.
  • 소멸자는 구조체에서는 사용할 수 없다. 클래스에서만 사용 가능하며 어떤 코드에서도 더 이상 인스턴스를 사용하지 못하게 될 때 소멸될 자격이 주어진다.
  • 인스턴스의 소멸자는 인스턴스가 소멸될 자격만 된다면 언제든 실행이 된다.
  • 인스턴스가 소멸될 때 소멸자는 상속 체인을 따라 자식-부모 순으로 순차적으로 호출된다.

Finalize

C#에서 Finalize 메소드는 표준 C++ 소멸자처럼 동작한다. C#에서는 Finalize라고 메소드에 이름 붙이는 것 대신 C++의 소멸자 문법처럼 물결 표시를 메소드명 앞에 붙인다.

Dispose

객체를 정리하기 위해 명시적으로 호출이 가능한 메소드 Close() 또는 Dispose()를 제공하는 것이 바람직하다. 소멸자는 GC에 의해 호출되기 때문이다.

IDisposable 인터페이스는 클래스가 가지고 있는 자원이 정리되어야 한다는 것을 알려주며 실제로 정리될 수 있는 방법을 제공해준다. 만약 소멸자를 직접 구현해야 한다면 그 클래스의 정리(Dispose) 메소드는 GC.SuppressFinalize() 메소드를 꼭 실행해 인스턴스를 강제적으로 제거해야 한다.

What to use?

명시적으로 소멸자를 호출하는 것은 허용되지 않는다. 소멸자는 가비지 컬렉터에 의해 호출된다. 만약 file을 다루는 것과 같이 처리 비용이 비싸 관리되지 않는 자원들을 다루게 되면 가능한한 빠르게 닫고 정리하기를 원할 것이다. 이런 경우에는 IDisposable 인터페이스를 구현해야 한다.


정말 상속되지 않는가

MSDN의 Destructors (C# Programming Guide)의 예제를 보면 상속은 아니지만 상속 순서에 따른 연쇄 호출(chaining)이 발생한다. 호출의 순서는 가장 하위 클래스의 소멸자부터 상위 클래스로 연쇄적으로 호출한다.

class First
{
    ~First()
    {
        System.Diagnostics.Trace.WriteLine("First's destructor is called.");
    }
}

class Second : First
{
    ~Second()
    {
        System.Diagnostics.Trace.WriteLine("Second's destructor is called.");
    }
}

class Third : Second
{
    ~Third()
    {
        System.Diagnostics.Trace.WriteLine("Third's destructor is called.");
    }
}

class TestDestructors
{
    static void Main()
    {
        Third t = new Third();
    }

}
/* Output (to VS Output Window):
    Third's destructor is called.
    Second's destructor is called.
    First's destructor is called.
*/