마무리 대 처리 Finalize방법을 사용합니까?Dispose 방법을

어떤 사람들은 왜이 Finalize방법을 사용합니까?Dispose 방법을 사용합니까?

어떤 상황에서 Finalize방법보다 방법 을 사용 Dispose하시겠습니까?



답변

다른 사람들은 이미 ( Dispose와 언어 정의에서 소멸 Finalize자라고하는 Finalize방법 사이의) 차이점을 이미 다루었 으므로 Finalize메소드가 유용한 시나리오에 대해 조금만 추가 할 것입니다.

일부 유형은 일회용 자원을 사용하고 폐기하기 쉬운 방식으로 일회용 자원을 캡슐화합니다. 일반적인 사용법은 종종 다음과 같습니다 : 열기, 읽기 또는 쓰기, 닫기 (처리). using구조 와 매우 잘 어울립니다 .

다른 사람들은 조금 더 어렵다. WaitEventHandles예를 들어 하나의 스레드에서 다른 스레드로 신호를 보내는 데 사용되므로 이와 같이 사용되지 않습니다. 그러면 질문은 누가 Dispose이것을 불러야 합니까? 이와 같은 보호 유형으로, Finalize메소드가 구현 되어 인스턴스가 더 이상 애플리케이션에서 참조되지 않을 때 자원이 삭제되도록합니다.


답변

finalizer 메소드는 객체가 가비지 수집 될 때 호출되며 이러한 상황이 언제 발생하는지 보장 할 수 없습니다 (강제화 할 수는 있지만 성능이 저하 될 수 있습니다).

Dispose반면에 방법은 당신이 청소하고 귀하가 취득한 모든 자원 (관리되지 않는 데이터, 데이터베이스 연결, 파일 핸들 등) 코드가 이루어집니다 순간을 해제 할 수 있도록 클래스를 생성 한 코드에 의해 호출하기위한 것입니다 당신의 물건.

표준 방법은 구현하는 것입니다 IDisposable그리고 Dispose당신은 당신의 객체를 사용할 수 있도록 using한 Statment. 와 같은 using(var foo = new MyObject()) { }. 그리고 종료 Dispose코드에서는 호출 코드가 처리하지 못한 경우를 대비하여 호출합니다.


답변

Finalize는 가비지 수집기가 개체를 회수 할 때 호출되는 백스톱 방법입니다. Dispose는 GC가 개체에 반올림 될 때까지 무기한으로 유지하지 않고 더 이상 필요하지 않을 때 유용한 네이티브 리소스 (창 핸들, 데이터베이스 연결 등)를 해제하기 위해 응용 프로그램에서 호출하는 “결정적 정리”방법입니다.

개체의 사용자는 항상 Dispose를 사용합니다. 마무리는 GC를위한 것입니다.

클래스의 구현 자로서 폐기해야하는 관리 자원을 보유하면 Dispose를 구현합니다. 네이티브 리소스를 보유하고 있으면 Dispose와 Finalize를 모두 구현하고 네이티브 리소스를 해제하는 일반적인 메서드를 호출합니다. 이러한 관용구는 일반적으로 호출을 true로 처리하고 호출을 false로 마무리하는 개인 Dispose (bool disposing) 방법을 통해 결합됩니다. 이 메소드는 항상 기본 자원을 해제 한 다음 처리 매개 변수를 확인하고, 참이면 관리 자원을 처리하고 GC.SuppressFinalize를 호출합니다.


답변

마무리

  • 종료 자 항상해야 protected하지, public또는 private메소드가 직접 응용 프로그램의 코드에서 호출 할 수 없습니다 수 있도록 함과 동시에, 그것은를 호출 할 수 base.Finalize방법을
  • 종료자는 관리되지 않는 리소스 만 해제해야합니다.
  • 프레임 워크는 종료자가 주어진 인스턴스에서 전혀 실행되지 않을 것이라고 보장하지 않습니다.
  • 종료 자에 메모리를 할당하거나 종료 자에서 가상 메소드를 호출하지 마십시오.
  • 파이널 라이저에서 동기화 및 처리되지 않은 예외를 발생시키지 마십시오.
  • 종료 자의 실행 순서는 결정적이지 않습니다. 즉, 종료 자 내에서 여전히 사용 가능한 다른 개체에 의존 할 수 없습니다.
  • 값 유형에 종료자를 정의하지 마십시오.
  • 빈 소멸자를 만들지 마십시오. 다시 말해, 클래스가 관리되지 않는 리소스를 정리해야하는 경우가 아니면 명시 적으로 소멸자를 정의해서는 안되며 정의한 경우 일부 작업을 수행해야합니다. 나중에 소멸자에서 관리되지 않는 리소스를 더 이상 정리할 필요가 없으면 제거하십시오.

처분

  • 종료 IDisposable자가있는 모든 유형에 구현
  • Dispose메소드를 호출 한 후 오브젝트를 사용할 수 없는지 확인하십시오 . 즉, Dispose메소드가 호출 된 후 오브젝트를 사용하지 마십시오 .
  • Dispose모든 IDisposable유형을 완료하면 전화하십시오 .
  • 허용 Dispose오차를 발생시키지 않고 여러 번 호출 할 수 있습니다.
  • Dispose메소드를 사용하여 GC.SuppressFinalize메소드 내에서 최종 호출을 나중에 억제
  • 일회용 값 유형을 생성하지 마십시오
  • Dispose메소드 내에서 예외를 던지지 마십시오

폐기 / 최종 패턴

  • Microsoft는 모두 구현하는 것을 권장 Dispose하고 Finalize관리되지 않는 리소스로 작업 할 때. Finalize구현이 실행됩니다 및 자원이 여전히 객체는 개발자가 전화를 무시하면 쓰레기도 수집 될 때 발표 될 것이다 Dispose명시 적 방법을.
  • Finalize방법과 방법 에서 관리되지 않는 리소스를 정리하십시오 Dispose. 또한 Dispose메서드에서 관리되지 않는 리소스를 멤버로 사용하여 해당 클래스 내부의 구성 요소로 사용하는 모든 .NET 개체에 대해 메서드를 호출하십시오 Dispose.

답변

이 개체를 더 이상 사용하지 않으면 GC에서 Finalize를 호출합니다.

Dispose는이 클래스의 사용자가 모든 리소스를 해제하기 위해 호출 할 수있는 일반적인 방법입니다.

사용자가 Dispose 호출을 잊어 버렸고 클래스에 Finalize가 구현되어 있으면 GC가 호출되는지 확인합니다.


답변

MCSD Certification Toolkit (시험 70-483) 문서 193에는 몇 가지 열쇠가 있습니다.

소멸자 ≈ (거의 같음)base.Finalize() , 소멸자는 소멸자의 코드를 실행 한 다음 기본 클래스의 Finalize 메소드를 호출하는 Finalize 메소드의 대체 버전으로 변환됩니다. 그렇다면 GC에 의존하기 때문에 언제 호출 될지 알 수없는 완전히 비 결정적입니다.

클래스에 관리 자원이없고 관리되지 않는 자원이 없으면 클래스를 구현 IDisposable하거나 소멸자가 없어야합니다 .

클래스에 managed resources 만있는 경우 구현해야 IDisposable하지만 소멸자가 없어야합니다. 소멸자가 실행될 때 관리 객체가 여전히 존재하는지 확인할 수 없으므로 해당 Dispose()메소드를 호출 할 수 없습니다 .

클래스에 관리되지 않는 리소스 만IDisposable 있는 경우 프로그램이 호출하지 않는 경우 소멸자 를 구현 해야합니다 Dispose().

Dispose()메소드는 두 번 이상 실행하기에 안전해야합니다. 변수를 사용하여 이전에 실행되었는지 여부를 추적하여이를 달성 할 수 있습니다.

Dispose()관리되는 리소스와 관리되지 않는 리소스를 모두 해제해야합니다 .

소멸자는 관리되지 않는 리소스 만 해제해야합니다 . 소멸자가 실행될 때 관리 대상 개체가 여전히 존재하는지 확인할 수 없으므로 Dispose 메서드를 호출 할 수 없습니다. 이는 표준 protected void Dispose(bool disposing)관리 패턴 을 사용하여 얻을 수 있으며 여기서 관리 자원 만 해제 (처리)됩니다 disposing == true.

리소스를 해제 한 후을 Dispose()호출해야GC.SuppressFinalize 개체가 종료 큐를 건너 뛸 수 있습니다.

관리되지 않고 관리되는 리소스가있는 클래스에 대한 구현 예 :

using System;

class DisposableClass : IDisposable
{
    // A name to keep track of the object.
    public string Name = "";

    // Free managed and unmanaged resources.
    public void Dispose()
    {
        FreeResources(true);

        // We don't need the destructor because
        // our resources are already freed.
        GC.SuppressFinalize(this);
    }

    // Destructor to clean up unmanaged resources
    // but not managed resources.
    ~DisposableClass()
    {
        FreeResources(false);
    }

    // Keep track if whether resources are already freed.
    private bool ResourcesAreFreed = false;

    // Free resources.
    private void FreeResources(bool freeManagedResources)
    {
        Console.WriteLine(Name + ": FreeResources");
        if (!ResourcesAreFreed)
        {
            // Dispose of managed resources if appropriate.
            if (freeManagedResources)
            {
                // Dispose of managed resources here.
                Console.WriteLine(Name + ": Dispose of managed resources");
            }

            // Dispose of unmanaged resources here.
            Console.WriteLine(Name + ": Dispose of unmanaged resources");

            // Remember that we have disposed of resources.
            ResourcesAreFreed = true;
        }
    }
}


답변

시간의 99 %는 걱정할 필요가 없습니다. 🙂 그러나 개체에 관리되지 않는 리소스 (예 : 창 핸들, 파일 핸들)에 대한 참조가 있으면 관리되는 개체가 해당 리소스를 해제 할 수있는 방법을 제공해야합니다. Finalize는 리소스 해제를 암시 적으로 제어합니다. 가비지 수집기에서 호출합니다. Dispose는 리소스 릴리스를 명시 적으로 제어 할 수있는 방법이며 직접 호출 할 수 있습니다.

가비지 콜렉션 의 주제에 대해 훨씬 더 배울 것이 있지만 그것은 시작입니다.