Share via


개체 수명: 개체가 만들어지고 소멸되는 방법

업데이트: 2007년 11월

New 키워드를 사용하여 클래스, 개체의 인스턴스가 만들어집니다. 새 개체가 사용되기 전에 초기화 작업이 먼저 수행되어야 하는 경우가 많습니다. 일반적인 초기화 작업으로는 파일 열기, 데이터베이스에 연결, 레지스트리 키의 값 읽기 등이 있습니다. Visual Basic에서는 초기화를 제어할 수 있도록 하는 특수 메서드인 생성자라는 프로시저를 사용하여 새 개체의 초기화를 제어합니다.

개체가 범위를 벗어나면 CLR(공용 언어 런타임)에 의해 개체가 해제됩니다. Visual Basic에서는 소멸자라는 프로시저를 사용하여 시스템 리소스의 해제를 제어합니다. 생성자와 소멸자 모두가 견고하고 예측 가능한 클래스 라이브러리를 만들 수 있도록 지원합니다.

Sub New 및 Sub Finalize

Sub New와 Sub Finalize 프로시저는 Visual Basic에서 개체를 초기화 및 소멸시키며 Visual Basic 6.0 이하 버전에서 사용되는 Class_Initialize와 Class_Terminate 메서드를 대신합니다. Sub New 생성자는 Class_Initialize와 달리 클래스가 만들어질 때 한 번만 실행될 수 있습니다. 이 생성자는 동일한 클래스나 파생 클래스에서 다른 생성자 코드의 첫 줄 외에는 아무 곳에서도 명시적으로 호출할 수 없습니다. 또한 Sub New 메서드의 코드는 항상 클래스의 다른 코드보다 먼저 실행됩니다. Visual Basic 2005 이상 버전에서는 사용자가 클래스에 대한 Sub New 프로시저를 명시적으로 정의하지 않는 경우 런타임에 암시적으로 Sub New 생성자를 만듭니다.

CLR는 개체를 해제하기 전에 Sub Finalize 프로시저를 정의하는 개체에 대해 Finalize 메서드를 자동으로 호출합니다. Finalize 메서드에는 파일을 닫고 상태 정보를 저장하는 것과 같이 개체가 소멸되기 직전에 실행해야 하는 코드가 포함될 수 있습니다. Sub Finalize를 실행할 경우 성능이 다소 저하되므로 개체를 명시적으로 해제해야 하는 경우에만 Sub Finalize 메서드를 정의해야 합니다.

참고:

CLR의 가비지 수집기에서는 운영 체제가 CLR 환경 외부에서 직접 실행하는 개체인 관리되지 않는 개체를 삭제할 수 없습니다. 삭제할 수 없는 이유는 관리되지 않는 여러 개체를 서로 다른 방식으로 삭제해야 하기 때문입니다. 그러한 정보는 관리되지 않는 개체에 직접 관련된 것이 아니므로 해당 개체에 대한 설명서에서 확인해야 합니다. 관리되지 않는 개체를 사용하는 클래스에서는 해당 Finalize 메서드에서 개체를 삭제해야 합니다.

Finalize 소멸자는 소속된 클래스 또는 파생 클래스에서만 호출할 수 있는 보호된 메서드입니다. 시스템에서는 개체가 소멸될 때 자동으로 Finalize를 호출하므로 파생 클래스의 Finalize 구현 외부에서 Finalize를 명시적으로 호출하지 않아야 합니다.

개체가 nothing으로 설정되는 즉시 실행되는 Class_Terminate와 달리 개체의 범위가 손실되는 시점과 Visual Basic에서 Finalize 소멸자를 호출하는 시점 사이에는 일반적으로 지연 시간이 있습니다. Visual Basic 2005 이상 버전에서는 두 번째 종류의 소멸자인 Dispose를 제공합니다. 언제든지 이 소멸자를 명시적으로 호출하여 리소스를 즉시 해제할 수 있습니다.

참고:

응용 프로그램에서 예외를 처리할 수 없으며 예외로 인해 응용 프로그램이 종료될 수 있기 때문에 Finalize 소멸자에서 예외를 throw하지 않아야 합니다.

IDisposable 인터페이스

클래스 인스턴스는 주로 Windows 핸들 및 데이터베이스 연결과 같이 CLR에서 관리하지 않는 리소스를 제어합니다. 이러한 리소스는 개체가 가비지 수집기에 의해 소멸될 때 해제되도록 클래스의 Finalize 메서드에서 삭제되어야 합니다. 그러나 가비지 수집기는 CLR에서 사용 가능한 메모리가 더 필요할 때만 개체를 소멸시킵니다. 즉, 개체가 범위를 벗어난 후 한참 있어야 리소스가 해제될 수 있습니다.

가비지 수집을 보완하기 위해 클래스에서 IDisposable 인터페이스를 구현하는 경우 시스템 리소스를 적극적으로 관리할 수 있는 메커니즘이 제공될 수 있습니다. IDisposable에는 클라이언트가 개체 사용을 완료할 때 호출해야 하는 Dispose 메서드 하나가 있습니다. Dispose 메서드를 사용하면 즉시 리소스를 해제하고 파일 닫기 및 데이터베이스 연결 등과 같은 작업을 수행할 수 있습니다. Finalize 소멸자와 달리 Dispose 메서드는 자동으로 호출되지 않습니다. 리소스를 즉시 해제하려는 경우 클래스의 클라이언트에서 Dispose를 명시적으로 호출해야 합니다.

IDisposable 구현

IDisposable 인터페이스를 구현하는 클래스에는 다음과 같은 코드 섹션이 포함되어야 합니다.

  • 개체가 삭제되었는지 여부를 추적하기 위한 필드

    Protected disposed As Boolean = False
    
  • 클래스의 리소스를 해제하는 Dispose의 오버로드. 이 메서드는 기본 클래스의 Dispose 및 Finalize 메서드에 의해 호출되어야 합니다.

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposed Then
            If disposing Then
                ' Insert code to free managed resources.
            End If
            ' Insert code to free unmanaged resources.
        End If
        Me.disposed = True
    End Sub
    
  • 다음 코드만 포함된 Dispose의 구현

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
  • 다음 코드만 포함된 Finalize 메서드의 재정의

    Protected Overrides Sub Finalize()
        Dispose(False)
        MyBase.Finalize()
    End Sub
    

IDisposable을 구현하는 클래스에서 파생

IDisposable 인터페이스를 구현하는 기본 클래스의 파생 클래스는 삭제해야 할 추가 리소스를 사용하지 않는 이상 기본 메서드를 재정의할 필요가 없습니다. 이러한 경우에는 파생 클래스에서 기본 클래스의 Dispose(disposing) 메서드를 재정의하여 파생 클래스의 리소스를 삭제해야 합니다. 이 재정의에서는 기본 클래스의 Dispose(disposing) 메서드를 호출해야 합니다.

Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    If Not Me.disposed Then
        If disposing Then
            ' Insert code to free managed resources.
        End If
        ' Insert code to free unmanaged resources.
    End If
    MyBase.Dispose(disposing)
End Sub

파생 클래스에서 기본 클래스의 Dispose 및 Finalize 메서드를 재정의하지 않아야 합니다. 그러한 메서드가 파생 클래스의 인스턴스로부터 호출되는 경우 기본 클래스의 해당 메서드 구현에서 파생 클래스의 Dispose(disposing) 메서드에 대한 재정의를 호출합니다.

시각화

다음 다이어그램에서는 파생 클래스에서 재정의되는 메서드와 상속되는 메서드를 보여 줍니다.

삭제 가능한 상속 그래픽

이 DisposeFinalize 패턴이 유지되면 파생 클래스와 기본 클래스의 리소스가 올바르게 삭제됩니다. 다음 다이어그램에서는 클래스가 삭제 및 종료될 때 호출되는 메서드를 보여 줍니다.

삭제 가능한 호출 그래픽

가비지 수집 및 Finalize 소멸자

.NET Framework에서는 사용되지 않은 리소스를 주기적으로 해제하는 참조 추적 가비지 수집 시스템을 사용합니다. Visual Basic 6.0 및 이전 버전에서는 참조 횟수라는 다른 시스템을 사용하여 리소스를 관리합니다. 두 시스템이 모두 자동으로 같은 함수를 수행하지만 몇 가지 중요한 차이점이 있습니다.

CLR는 시스템에서 특정 개체가 필요 없는 개체로 확인되면 해당 개체를 주기적으로 소멸시킵니다. 개체는 시스템 리소스가 부족하면 좀 더 빠르게 해제되고 그렇지 않은 경우에는 해제되는 빈도가 적습니다. Visual Basic 6.0 및 이전 버전 개체와는 달리 개체가 범위를 상실하는 시기와 CLR가 해당 개체를 해제하는 시기 사이에는 차이가 있으므로 개체가 소멸되는 시기를 정확하게 알 수 없습니다. 이러한 경우 개체가 명확하지 않은 수명을 가지는 것으로 간주됩니다. 대부분의 경우 개체가 범위를 상실할 때 Finalize 소멸자가 즉시 실행되지 않을 수도 있다는 사실을 유의한다면 명확하지 않은 수명으로 인해 응용 프로그램의 작성 방법이 변경되지는 않습니다.

가비지 수집 시스템 간의 다른 차이점에는 Nothing의 사용이 포함됩니다. Visual Basic 6.0 및 이전 버전에서 참조 횟수를 사용하기 위해 프로그래머는 개체 변수에 Nothing을 할당하여 해당 변수에 적용된 참조를 해제한 경우가 있습니다. 변수가 개체에 대한 마지막 참조를 보유하는 경우 해당 개체의 리소스는 즉시 해제되었습니다. 이후 버전의 Visual Basic에서도 이 프로시저를 계속 유용하게 사용할 수는 있지만 이로 인해 참조된 개체가 해당 리소스를 즉시 해제하지는 않습니다. 리소스를 즉시 해제하려면 개체의 Dispose 메서드를 사용합니다. 변수를 Nothing으로 설정해야 하는 유일한 경우는 해당 수명이 가비지 수집기가 고아 개체를 검색하는 데 걸리는 시간보다 긴 경우입니다.

참고 항목

작업

방법: Dispose Finalize 패턴 구현(Visual Basic)

개념

구성 요소의 초기화 및 종료

Finalize 메서드 및 소멸자

참조

생성자 및 소멸자 사용

New(Visual Basic)

Dispose

Nothing(Visual Basic)

기타 리소스

Visual Basic 6.0 사용자를 위한 언어 변경 사항